11using System ;
2- using System . Diagnostics ;
32using System . IO ;
43using System . Threading . Tasks ;
4+ using TextFileConvert . Converters ;
55
66namespace TextFileConvert ;
77
88public class ConvertLineEndings
99{
10- private const byte Cr = 13 ; //'\r'; // Carriage Return
11- private const byte Lf = 10 ; //'\n'; // Line Feed
12-
13- /// <summary>
14- /// These are the different conversions that this library can perform.
15- /// </summary>
16- private enum TextConvertMode
17- {
18- Dos2Ux ,
19- Ux2Dos
20- // Dos2Mac
21- // Mac2Dos
22- // Mac2Ux
23- // Ux2Mac
24- }
25-
2610 /// <summary>
2711 /// Converts a DOS text file to have Unix line endings.
2812 /// </summary>
@@ -31,7 +15,7 @@ private enum TextConvertMode
3115 /// <returns>Exit code.</returns>
3216 public static async Task < int > Dos2Ux ( string originalFile , string newFile )
3317 {
34- return await ReplaceLineEndings ( originalFile , newFile , TextConvertMode . Dos2Ux ) ;
18+ return await ReplaceLineEndings ( originalFile , newFile , new ConvertDos2Ux ( ) ) ;
3519 }
3620
3721 /// <summary>
@@ -42,7 +26,7 @@ public static async Task<int> Dos2Ux(string originalFile, string newFile)
4226 /// <returns>Exit code.</returns>
4327 public static async Task < int > Ux2Dos ( string originalFile , string newFile )
4428 {
45- return await ReplaceLineEndings ( originalFile , newFile , TextConvertMode . Ux2Dos ) ;
29+ return await ReplaceLineEndings ( originalFile , newFile , new ConvertUx2Dos ( ) ) ;
4630 }
4731
4832 /// <summary>
@@ -52,7 +36,7 @@ public static async Task<int> Ux2Dos(string originalFile, string newFile)
5236 /// <param name="newFile">The name of a new file to create.</param>
5337 /// <param name="convertMode">This is the type of conversion we are going to perform.</param>
5438 /// <returns>Exit code. 0 is success. -1 is a symbolic link.</returns>
55- private static async Task < int > ReplaceLineEndings ( string originalFile , string newFile , TextConvertMode convertMode )
39+ private static async Task < int > ReplaceLineEndings ( string originalFile , string newFile , ITextConverter convertMode )
5640 {
5741 try
5842 {
@@ -61,113 +45,20 @@ private static async Task<int> ReplaceLineEndings(string originalFile, string ne
6145 return - 1 ;
6246
6347 using var oldFileStream = new FileStream ( originalFile , FileMode . Open , FileAccess . Read , FileShare . Read , 65536 , FileOptions . Asynchronous ) ;
64-
65- // Attempt to detect encoding we will use for reading and writing
66- var fileEncoding = await Common . GetEncoding ( oldFileStream ) ;
67- Debug . Print ( fileEncoding . ToString ( ) ) ;
68-
69- // Rewind stream
70- oldFileStream . Position = 0L ;
71- await oldFileStream . FlushAsync ( ) ;
48+ using var newFileStream = new FileStream ( newFile , FileMode . Create , FileAccess . ReadWrite , FileShare . None , 65536 , FileOptions . Asynchronous ) ;
7249
7350 // Reading and writing is done in this one line
74- await WriteConvertedText ( oldFileStream , convertMode , newFile ) ;
51+ convertMode . WriteConvertedText ( oldFileStream , newFileStream ) ;
52+ await oldFileStream . FlushAsync ( ) ;
53+ await newFileStream . FlushAsync ( ) ;
7554 }
7655 catch ( Exception ex )
7756 {
78- Debug . Print ( "Error: " + ex . Message + Environment . NewLine + "Number: " + ex . HResult . ToString ( ) ) ;
57+ Console . WriteLine ( $ "Error: { ex . Message } ") ;
58+ Console . WriteLine ( $ "Number: { ex . HResult } ") ;
7959 return ex . HResult ;
8060 }
8161
8262 return 0 ;
8363 }
84-
85- /// <summary>
86- /// This is where the actual conversion logic lives.
87- /// </summary>
88- /// <param name="originalFile">The file you want to convert.</param>
89- /// <param name="convertMode">The type of conversion you want to perform.</param>
90- /// <param name="newFile">Full path to the new file to write</param>
91- /// <returns>The full text of the file with new line endings.</returns>
92- private static async Task WriteConvertedText ( FileStream originalFile , TextConvertMode convertMode , string newFile )
93- {
94- //using var oldFile = new StreamReader(originalFile, fileEncoding, true);
95- using var newFileStream = new FileStream ( newFile , FileMode . Create , FileAccess . ReadWrite , FileShare . None , 65536 , FileOptions . Asynchronous ) ;
96- switch ( convertMode )
97- {
98- case TextConvertMode . Dos2Ux :
99- {
100- while ( originalFile . CanRead )
101- {
102- var readBuffer = new byte [ 1 ] ;
103- int readChars = await originalFile . ReadAsync ( readBuffer , 0 , 1 ) ;
104- if ( readChars == 0 ) break ;
105-
106- // Look for Dos line endings
107- if ( readBuffer [ 0 ] == Cr )
108- {
109- // Strip out CR chars if followed by LF
110- var peekBuffer = new byte [ 1 ] ;
111- readChars = await originalFile . ReadAsync ( peekBuffer , 0 , 1 ) ;
112- if ( readChars == 0 ) break ;
113-
114- if ( peekBuffer [ 0 ] != Lf )
115- {
116- originalFile . Position -= 1 ;
117- }
118- else
119- {
120- readBuffer = peekBuffer ;
121- }
122- }
123-
124- await newFileStream . WriteAsync ( readBuffer , 0 , 1 ) ;
125- }
126-
127- break ;
128- }
129- case TextConvertMode . Ux2Dos :
130- {
131- while ( originalFile . CanRead )
132- {
133- var readBuffer = new byte [ 1 ] ;
134- int readChars = await originalFile . ReadAsync ( readBuffer , 0 , 1 ) ;
135- if ( readChars == 0 ) break ;
136-
137- // Check for CR first to avoid doubling the CR character when LF is found
138- if ( readBuffer [ 0 ] == Cr )
139- {
140- var peekBuffer = new byte [ 1 ] ;
141- readChars = await originalFile . ReadAsync ( peekBuffer , 0 , 1 ) ;
142- if ( readChars == 0 ) break ;
143-
144- if ( peekBuffer [ 0 ] == Lf )
145- {
146- // This is a DOS line ending, keep it.
147- Array . Resize ( ref readBuffer , 2 ) ;
148- readBuffer [ 1 ] = peekBuffer [ 0 ] ;
149- }
150- else
151- {
152- // Rewind
153- newFileStream . Position -= 1 ;
154- }
155- }
156- else if ( readBuffer [ 0 ] == Lf )
157- {
158- // This is a Unix line ending. Add preceding CR.
159- readBuffer = new byte [ 2 ] ;
160- readBuffer [ 0 ] = Cr ;
161- readBuffer [ 1 ] = Lf ;
162- }
163-
164- await newFileStream . WriteAsync ( readBuffer , 0 , readBuffer . Length ) ;
165- }
166-
167- break ;
168- }
169- default :
170- throw new ArgumentOutOfRangeException ( nameof ( convertMode ) , convertMode , "TextConvertMode not yet supported." ) ;
171- }
172- }
17364}
0 commit comments