特定の文字を使用してファイルを分割する必要があるという要件があります。デフォルトの分割オプションは、CRLF、LF、およびCRです。
これらの場合、私は行をそれぞれ\ r\nと\nと\rで分割しています。
また、任意のサイズのファイルを処理する必要があるという要件があります。(処理とは、基本的に、指定された文字列をファイルの指定された位置に挿入することです)。
このために、私は1024バイトのチャンクでファイルを読み取っています。
次に、string.Split()メソッドを適用します。Split()メソッドは、空白を無視するためのオプションを提供します。
これらの改行文字を行に追加し直す必要があります。このために、私はバイナリライターを使用しており、バイト配列を新しいファイルに書き込んでいます。問題:-
1)改行がCRLFで、分割オプションがNONEの場合、分割された配列にスペースも追加されます。2番目のオプションが指定されています(空白を無視するため)CRLFは正しく機能します。
2)空白を無視するビットオプションは、ファイルをバイト単位で読み取っているため、空白を無視できないため、他の問題を引き起こします。
3)改行文字がデフォルト以外の場合(例:'|')、結果の行にnull値が付加されます。
誰かが私の問題の解決策を与えることができますか?
これが私が書いた方法です
private static void ProcessOriginalFile(string filePath, string destinationFilePath, int fromPosition, int toPosition, string lineBreakCharacter, string replaceString, long fileSize, bool ignoreHeader, bool ignoreFooter)
{
int chunkSize = fileSize < 1024 ? (int)fileSize : 1024;//bytes
byte[] chunkData = new byte[chunkSize];
char[] charactersSeparator=new char[1];
charactersSeparator = CommonOperations.ResolveTheRecordBreak(lineBreakCharacter);
int totalLineBreakCharactersLength = 0;
for (int i = 0; i < charactersSeparator.Length; i++)
{
if (charactersSeparator[i] == 0)
break;
totalLineBreakCharactersLength = totalLineBreakCharactersLength + BitConverter.GetBytes(charactersSeparator[i]).Length;
}
using (BinaryReader fileReader = new BinaryReader(new FileStream(filePath, FileMode.Open)))
{
string lastChunk = string.Empty;
string chunkcontents = string.Empty;
IList<byte[]> dataToBeWritten = new List<byte[]>();
while (fileSize > 0)
{
chunkData = fileReader.ReadBytes(chunkSize);
byte[] chunkToBeWritten = new byte[chunkSize];
chunkcontents = chunkcontents + System.Text.ASCIIEncoding.UTF8.GetString(chunkData);
string[] splittedArray = new string[1];
splittedArray = chunkcontents.Split(charactersSeparator, StringSplitOptions.RemoveEmptyEntries);
if (ignoreHeader)
{
splittedArray = splittedArray.Skip(1).ToArray();
ignoreHeader = false;
if (splittedArray.Count() == 0)
continue;
}
int count = 0;
if (splittedArray != null || splittedArray.Count() > 0)
{
foreach (string str in splittedArray)
{
++count;
if (count != splittedArray.Length)
{
string stringToBeEdited = string.Empty;
stringToBeEdited = str;
if (stringToBeEdited.Length < (toPosition + 1))
throw new Exception("Position exceeds the string length. Line contents are : " + stringToBeEdited + " String length is : " + stringToBeEdited.Length + " To Position is : " + toPosition);
//replace the text between from and two positions with the replaced string
stringToBeEdited = stringToBeEdited.Remove(fromPosition, toPosition + 1 - fromPosition).Insert(fromPosition, replaceString);
//clear the array
dataToBeWritten.Clear();
AddLineBreakCharacter(lineBreakCharacter, charactersSeparator, totalLineBreakCharactersLength, dataToBeWritten, ref chunkToBeWritten, ref stringToBeEdited);
//write data using binary writer
WriteBinaryDataToFile(destinationFilePath, dataToBeWritten);
totalLinesProcessed++;
}
else
{
lastChunk = str;
chunkcontents = str;
}
}
}
fileSize = fileSize - chunkSize;
/*if file size is less than the chunksize*2, then chunk size should be the file size
* and chunkdata array length should be that of the file size*/
if (fileSize < (chunkSize * 2))
{
chunkSize = (int)fileSize;
chunkData = new byte[chunkSize];
}
}
if (!string.IsNullOrEmpty(lastChunk))
{
if (ignoreFooter == false)
{
if (lastChunk.Length >= toPosition + 1)
lastChunk = lastChunk.Remove(fromPosition, toPosition + 1 - fromPosition).Insert(fromPosition, replaceString);
else
throw new Exception("Position exceeds in the last line of the file. Line contents are : " + lastChunk + " String length is : " + lastChunk.Length + " To Position is : " + toPosition);
dataToBeWritten.Clear();
byte[] chunkToBeWritten = new byte[chunkSize];
AddLineBreakCharacter(lineBreakCharacter, charactersSeparator, totalLineBreakCharactersLength, dataToBeWritten, ref chunkToBeWritten, ref lastChunk);
WriteBinaryDataToFile(destinationFilePath, dataToBeWritten);
totalLinesProcessed++;
}
}
}
}
private static void WriteBinaryDataToFile(string destinationFilePath, IList<byte[]> chunkToBeWritten)
{
using (FileStream fileSream = new FileStream(destinationFilePath, FileMode.Append))
{
using (BinaryWriter outfile = new BinaryWriter(fileSream, Encoding.ASCII))
{
foreach (byte[] item in chunkToBeWritten)
{
outfile.Write(item);
}
}
}
}
private static void AddLineBreakCharacter(string lineBreakCharacter, char[] charactersSeparator, int totalLineBreakCharactersLength, IList<byte[]> dataToBeWritten, ref byte[] chunkToBeWritten, ref string stringToBeEdited)
{
switch (lineBreakCharacter)
{
case CommonConstants.NEW_LINE:
stringToBeEdited = stringToBeEdited + CommonConstants.CARRIAGE_RETURN_CHARACTER + CommonConstants.NEW_LINE_CHARACTER;
chunkToBeWritten = System.Text.Encoding.UTF8.GetBytes(stringToBeEdited);
//add modified line
dataToBeWritten.Add(chunkToBeWritten);
break;
case CommonConstants.LINE_FEED:
stringToBeEdited = stringToBeEdited + CommonConstants.NEW_LINE_CHARACTER;
chunkToBeWritten = System.Text.Encoding.UTF8.GetBytes(stringToBeEdited);
//add modified line
dataToBeWritten.Add(chunkToBeWritten);
break;
case CommonConstants.CARRIAGE_RETURN:
stringToBeEdited = stringToBeEdited + CommonConstants.CARRIAGE_RETURN_CHARACTER;
chunkToBeWritten = System.Text.Encoding.UTF8.GetBytes(stringToBeEdited);
//add modified line
dataToBeWritten.Add(chunkToBeWritten);
break;
default:
chunkToBeWritten = System.Text.Encoding.UTF8.GetBytes(stringToBeEdited);
//add modified line
dataToBeWritten.Add(chunkToBeWritten);
byte[] seperatorCharArray = new byte[totalLineBreakCharactersLength];
int destinationIndex = 0;
foreach (char ch in charactersSeparator)
{
if (ch == 0)
break;
//convert the character to byte array
byte[] charArr = BitConverter.GetBytes(ch);
//copy character bytes to seperator character array
Array.Copy(charArr, 0, seperatorCharArray, destinationIndex, charArr.Length);
}
//add line break characters array to list
dataToBeWritten.Add(seperatorCharArray);
break;
}
}