Skip to content

Commit 3f459c8

Browse files
Merge pull request #4 from A9G-Data-Droid/csharp
Convert to Csharp
2 parents d466f46 + 6388a3c commit 3f459c8

19 files changed

+511
-386
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System.Diagnostics;
2+
using System.IO;
3+
using System.Threading.Tasks;
4+
using Microsoft.VisualStudio.TestTools.UnitTesting;
5+
using TextFileConvert;
6+
7+
8+
9+
namespace TestLineEndingConversion;
10+
11+
[TestClass]
12+
public class IntegrationTesting
13+
{
14+
private const string TestUnixTxt = "testunix.txt";
15+
private const string TestDosTxt = "testdos.txt";
16+
17+
[TestMethod]
18+
public async Task TestDos2Ux()
19+
{
20+
// Where am I?
21+
Debug.WriteLine(Directory.GetCurrentDirectory());
22+
if(File.Exists(TestUnixTxt))
23+
File.Delete(TestUnixTxt);
24+
25+
// ensure we start well
26+
var precondition = await File.ReadAllTextAsync("dos.txt");
27+
Assert.IsTrue(precondition.Contains("\r\n"));
28+
29+
// Do Conversion
30+
var exitCode = await ConvertLineEndings.Dos2Ux("dos.txt", TestUnixTxt);
31+
32+
// Zero is success
33+
Assert.AreEqual(exitCode, 0);
34+
35+
// Compare the test file to the artifact file
36+
var result = await File.ReadAllTextAsync(TestUnixTxt);
37+
Assert.IsFalse(result.Contains("\r\n"));
38+
Assert.AreEqual(await File.ReadAllTextAsync("unix.txt"), result);
39+
40+
// Clean up
41+
File.Delete(TestUnixTxt);
42+
}
43+
44+
[TestMethod]
45+
public async Task TestUx2Dos()
46+
{
47+
// Where am I?
48+
Debug.WriteLine(Directory.GetCurrentDirectory());
49+
50+
if(File.Exists(TestDosTxt))
51+
File.Delete(TestDosTxt);
52+
53+
// ensure we start well
54+
var precondition = await File.ReadAllTextAsync("unix.txt");
55+
Assert.IsFalse(precondition.Contains("\r\n"));
56+
57+
// Do Conversion
58+
int exitCode = await ConvertLineEndings.Ux2Dos("unix.txt", TestDosTxt);
59+
60+
// Zero is success
61+
Assert.AreEqual(exitCode, 0);
62+
63+
// Compare the test file to the artifact file
64+
var result = await File.ReadAllTextAsync(TestDosTxt);
65+
Assert.IsTrue(result.Contains("\r\n"));
66+
Assert.AreEqual(await File.ReadAllTextAsync("dos.txt"), result);
67+
68+
// Clean up
69+
File.Delete(TestDosTxt);
70+
}
71+
}

TestLineEndingConversion/IntegrationTesting.vb

Lines changed: 0 additions & 47 deletions
This file was deleted.

TestLineEndingConversion/TestLineEndingConversion.vbproj renamed to TestLineEndingConversion/TestLineEndingConversion.csproj

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
2-
1+
<Project Sdk="Microsoft.NET.Sdk">
32
<PropertyGroup>
43
<RootNamespace>TestLineEndingConversion</RootNamespace>
5-
<TargetFramework>net5.0</TargetFramework>
6-
4+
<TargetFramework>net8.0</TargetFramework>
75
<IsPackable>false</IsPackable>
6+
<DefaultItemExcludes>$(DefaultItemExcludes);$(ProjectDir)**\*.vb</DefaultItemExcludes>
7+
<LangVersion>latest</LangVersion>
88
</PropertyGroup>
9-
109
<ItemGroup>
11-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
12-
<PackageReference Include="MSTest.TestAdapter" Version="2.2.3" />
13-
<PackageReference Include="MSTest.TestFramework" Version="2.2.3" />
14-
<PackageReference Include="coverlet.collector" Version="3.0.2" />
10+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
11+
<PackageReference Include="MSTest.TestAdapter" Version="3.6.0" />
12+
<PackageReference Include="MSTest.TestFramework" Version="3.6.0" />
13+
<PackageReference Include="coverlet.collector" Version="6.0.2">
14+
<PrivateAssets>all</PrivateAssets>
15+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
16+
</PackageReference>
1517
</ItemGroup>
16-
1718
<ItemGroup>
18-
<ProjectReference Include="..\TextFileConvert\TextFileConvert.vbproj" />
19+
<ProjectReference Include="..\TextFileConvert\TextFileConvert.csproj" />
1920
</ItemGroup>
20-
2121
<ItemGroup>
2222
<None Update="dos.txt">
2323
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
@@ -29,5 +29,4 @@
2929
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
3030
</None>
3131
</ItemGroup>
32-
33-
</Project>
32+
</Project>

TextFileConvert.sln

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,36 @@ Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio Version 16
44
VisualStudioVersion = 16.0.31613.86
55
MinimumVisualStudioVersion = 10.0.40219.1
6-
Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "TextFileConvert", "TextFileConvert\TextFileConvert.vbproj", "{C6D516A4-A83D-405A-8F46-DF37C9C25D4B}"
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TextFileConvert", "TextFileConvert\TextFileConvert.csproj", "{74F197CF-6465-0FAB-0D1E-1549AB5569EB}"
77
EndProject
8-
Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "dos2ux", "dos2ux\dos2ux.vbproj", "{AA1FC840-1A4A-4F07-BAFC-8B281CEE6F10}"
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dos2ux", "dos2ux\dos2ux.csproj", "{183B492B-D612-00F6-38A4-41567E795BB0}"
99
EndProject
10-
Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "ux2dos", "ux2dos\ux2dos.vbproj", "{C596EC73-1634-429E-A20C-CD73DB6D416C}"
10+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ux2dos", "ux2dos\ux2dos.csproj", "{77B26D18-DA6C-0D6F-2054-070DB9FA75CC}"
1111
EndProject
12-
Project("{778DAE3C-4631-46EA-AA77-85C1314464D9}") = "TestLineEndingConversion", "TestLineEndingConversion\TestLineEndingConversion.vbproj", "{FC6A6D47-7C99-41D6-BD55-C6394BF804C4}"
12+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestLineEndingConversion", "TestLineEndingConversion\TestLineEndingConversion.csproj", "{4E4EEC2C-B0C1-0E27-3F0D-0C47296F3064}"
1313
EndProject
1414
Global
1515
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1616
Debug|Any CPU = Debug|Any CPU
1717
Release|Any CPU = Release|Any CPU
1818
EndGlobalSection
1919
GlobalSection(ProjectConfigurationPlatforms) = postSolution
20-
{C6D516A4-A83D-405A-8F46-DF37C9C25D4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21-
{C6D516A4-A83D-405A-8F46-DF37C9C25D4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
22-
{C6D516A4-A83D-405A-8F46-DF37C9C25D4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
23-
{C6D516A4-A83D-405A-8F46-DF37C9C25D4B}.Release|Any CPU.Build.0 = Release|Any CPU
24-
{AA1FC840-1A4A-4F07-BAFC-8B281CEE6F10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25-
{AA1FC840-1A4A-4F07-BAFC-8B281CEE6F10}.Debug|Any CPU.Build.0 = Debug|Any CPU
26-
{AA1FC840-1A4A-4F07-BAFC-8B281CEE6F10}.Release|Any CPU.ActiveCfg = Release|Any CPU
27-
{AA1FC840-1A4A-4F07-BAFC-8B281CEE6F10}.Release|Any CPU.Build.0 = Release|Any CPU
28-
{C596EC73-1634-429E-A20C-CD73DB6D416C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29-
{C596EC73-1634-429E-A20C-CD73DB6D416C}.Debug|Any CPU.Build.0 = Debug|Any CPU
30-
{C596EC73-1634-429E-A20C-CD73DB6D416C}.Release|Any CPU.ActiveCfg = Release|Any CPU
31-
{C596EC73-1634-429E-A20C-CD73DB6D416C}.Release|Any CPU.Build.0 = Release|Any CPU
32-
{FC6A6D47-7C99-41D6-BD55-C6394BF804C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33-
{FC6A6D47-7C99-41D6-BD55-C6394BF804C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
34-
{FC6A6D47-7C99-41D6-BD55-C6394BF804C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
35-
{FC6A6D47-7C99-41D6-BD55-C6394BF804C4}.Release|Any CPU.Build.0 = Release|Any CPU
20+
{74F197CF-6465-0FAB-0D1E-1549AB5569EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21+
{74F197CF-6465-0FAB-0D1E-1549AB5569EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
22+
{74F197CF-6465-0FAB-0D1E-1549AB5569EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
23+
{74F197CF-6465-0FAB-0D1E-1549AB5569EB}.Release|Any CPU.Build.0 = Release|Any CPU
24+
{183B492B-D612-00F6-38A4-41567E795BB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25+
{183B492B-D612-00F6-38A4-41567E795BB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
26+
{183B492B-D612-00F6-38A4-41567E795BB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
27+
{183B492B-D612-00F6-38A4-41567E795BB0}.Release|Any CPU.Build.0 = Release|Any CPU
28+
{77B26D18-DA6C-0D6F-2054-070DB9FA75CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29+
{77B26D18-DA6C-0D6F-2054-070DB9FA75CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
30+
{77B26D18-DA6C-0D6F-2054-070DB9FA75CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
31+
{77B26D18-DA6C-0D6F-2054-070DB9FA75CC}.Release|Any CPU.Build.0 = Release|Any CPU
32+
{4E4EEC2C-B0C1-0E27-3F0D-0C47296F3064}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33+
{4E4EEC2C-B0C1-0E27-3F0D-0C47296F3064}.Debug|Any CPU.Build.0 = Debug|Any CPU
34+
{4E4EEC2C-B0C1-0E27-3F0D-0C47296F3064}.Release|Any CPU.ActiveCfg = Release|Any CPU
35+
{4E4EEC2C-B0C1-0E27-3F0D-0C47296F3064}.Release|Any CPU.Build.0 = Release|Any CPU
3636
EndGlobalSection
3737
GlobalSection(SolutionProperties) = preSolution
3838
HideSolutionNode = FALSE

TextFileConvert/Common.cs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using System;
2+
using System.IO;
3+
using System.Text;
4+
5+
namespace TextFileConvert;
6+
7+
public static class Common
8+
{
9+
public const byte Cr = 13; //'\r'; // Carriage Return
10+
public const byte Lf = 10; //'\n'; // Line Feed
11+
12+
/// <summary>
13+
/// This is the command line help that is displayed when invalid parameters are given.
14+
/// </summary>
15+
/// <param name="programName"></param>
16+
public static void PrintUsage(string programName)
17+
{
18+
Console.WriteLine("""
19+
20+
NAME
21+
{0} - Text file format converter
22+
23+
SYNOPSIS
24+
{0} old-filename new-filename
25+
26+
DESCRIPTION
27+
{0} reads old-filename and writes out new-filename, converting line endings.
28+
29+
""", programName);
30+
}
31+
32+
/// <summary>
33+
/// Attempt to detect the encoding of a file.
34+
/// </summary>
35+
/// <param name="theFile">The file to get the encoding pattern from.</param>
36+
/// <returns>Encoding type, defaults to ASCII.</returns>
37+
[Obsolete("No longer used internally. Prefer native methods.")]
38+
public static Encoding GetEncoding(FileStream theFile)
39+
{
40+
var bom = new byte[4];
41+
var count = theFile.Read(bom, 0, 4);
42+
43+
// Detect BOM type
44+
if (count > 2 && bom[0] == 0x2B && bom[1] == 0x2F && bom[2] == 0x76)
45+
{
46+
return Encoding.UTF7;
47+
}
48+
if (count > 2 && bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF)
49+
{
50+
return Encoding.UTF8;
51+
}
52+
if (count > 1 && bom[0] == 0xFF && bom[1] == 0xFE)
53+
{
54+
return Encoding.Unicode;
55+
}
56+
if (count > 1 && bom[0] == 0xFE && bom[1] == 0xFF)
57+
{
58+
return Encoding.BigEndianUnicode;
59+
}
60+
if (count > 3 && bom[0] == 0 && bom[1] == 0 && bom[2] == 0xFE && bom[3] == 0xFF)
61+
{
62+
return Encoding.UTF32;
63+
}
64+
65+
// Default to
66+
return Encoding.ASCII;
67+
}
68+
69+
/// <summary>
70+
/// Detect when the file in the given path is a symbolic link.
71+
/// WARNING: Could have false positive for any file with a reparse point that is not a symbolic link.
72+
/// </summary>
73+
/// <param name="path">Full path to file to test.</param>
74+
/// <returns>True if Reparse Point is found.</returns>
75+
public static bool IsSymbolic(string path)
76+
{
77+
var pathInfo = new FileInfo(path);
78+
return pathInfo.Attributes.HasFlag(FileAttributes.ReparsePoint);
79+
}
80+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
using System;
2+
using System.IO;
3+
using System.Threading.Tasks;
4+
using TextFileConvert.Converters;
5+
6+
namespace TextFileConvert;
7+
8+
public class ConvertLineEndings
9+
{
10+
/// <summary>
11+
/// Converts a DOS text file to have Unix line endings.
12+
/// </summary>
13+
/// <param name="originalFile">The file to convert.</param>
14+
/// <param name="newFile">The name of a new file to create.</param>
15+
/// <returns>Exit code.</returns>
16+
public static async Task<int> Dos2Ux(string originalFile, string newFile)
17+
{
18+
return await ReplaceLineEndings(originalFile, newFile, new ConvertDos2Ux());
19+
}
20+
21+
/// <summary>
22+
/// Converts a DOS text file to have Unix line endings.
23+
/// </summary>
24+
/// <param name="originalFile">The file to convert.</param>
25+
/// <param name="newFile">The name of a new file to create.</param>
26+
/// <returns>Exit code.</returns>
27+
public static async Task<int> Ux2Dos(string originalFile, string newFile)
28+
{
29+
return await ReplaceLineEndings(originalFile, newFile, new ConvertUx2Dos());
30+
}
31+
32+
/// <summary>
33+
/// Loads a whole text file in to memory, Performs a find\replace, and writes a new file.
34+
/// </summary>
35+
/// <param name="originalFile">The file path to convert.</param>
36+
/// <param name="newFile">The name of a new file to create.</param>
37+
/// <param name="convertMode">This is the type of conversion we are going to perform.</param>
38+
/// <returns>Exit code. 0 is success. -1 is a symbolic link.</returns>
39+
private static async Task<int> ReplaceLineEndings(string originalFile, string newFile, ITextConverter convertMode)
40+
{
41+
try
42+
{
43+
// Do not attempt to work on symbolic links
44+
if (Common.IsSymbolic(originalFile))
45+
return -1;
46+
47+
using var oldFileStream = new FileStream(originalFile, FileMode.Open, FileAccess.Read, FileShare.Read, 65536, FileOptions.Asynchronous);
48+
using var newFileStream = new FileStream(newFile, FileMode.Create, FileAccess.ReadWrite, FileShare.None, 65536, FileOptions.Asynchronous);
49+
50+
// Reading and writing is done in this one line
51+
convertMode.WriteConvertedText(oldFileStream, newFileStream);
52+
await oldFileStream.FlushAsync();
53+
await newFileStream.FlushAsync();
54+
}
55+
catch (Exception ex)
56+
{
57+
Console.WriteLine($"Error: {ex.Message}");
58+
Console.WriteLine($"Number: {ex.HResult}");
59+
return ex.HResult;
60+
}
61+
62+
return 0;
63+
}
64+
}

0 commit comments

Comments
 (0)