背景: 設計が不十分な EBCDIC ファイルに ASCII 行ターミネータを使用するバイナリ データを使用するアプリケーションを作成する必要があり、そのバイナリ データに ASCII CRLF が含まれていることがあり、行が正しく分割されないことがあります。この古いファイル形式を使用して、各レコードの最後に CRLF をドロップする必要があります。
エンコーディングで aStreamReader
を使用すると、メソッドが期待どおりではなく行末としてのみ読み取られるようになるため、返されるすべての文字列 (最初の文字列以降) は LF ( ASCII) で始まります。IBM037
ReadLine()
\r
\r\n
ReadLine
0A
問題を再現するサンプル プログラム:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
class Program
{
static void Main(string[] args)
{
//generate example EBCDIC data
List<byte> bytes = new List<byte>();
Encoding EBCDIC = Encoding.GetEncoding("IBM037");
bytes.AddRange(Encoding.Convert(Encoding.ASCII, EBCDIC, Encoding.ASCII.GetBytes("Some nice ascii text")));
bytes.AddRange(new byte[] { (byte)'\r', (byte)'\n' });
bytes.AddRange(Encoding.Convert(Encoding.ASCII, EBCDIC, Encoding.ASCII.GetBytes("Some more nice ascii text")));
//read it using StreamReader
using(MemoryStream ms = new MemoryStream(bytes.ToArray()))
using (StreamReader reader = new StreamReader(ms, EBCDIC))
{
string line = string.Empty;
while ((line = reader.ReadLine()) != null)
{
EBCDIC.GetBytes(line).ToList().ForEach(c => Console.Write(c));
Console.WriteLine();
}
}
Console.ReadLine();
}
}
出力は次のようになります。
226150148133641491371311336412916213113713764163133167163
1022615014813364148150153133641491371311336412916213113713764163133167163
2 行目の先頭にある 10 は存在しないはずです。これは、CRLF シーケンスの LF であるためです。
ReadLine
この方法についての私の理解は次のとおりです。
行は、一連の文字の後にライン フィード ("\n")、キャリッジ リターン ("\r")、またはキャリッジ リターンの直後にライン フィード ("\r\n") が続くものとして定義されます。返される文字列には、終了のキャリッジ リターンまたはライン フィードは含まれません。ソース
エンコーディングがそれを変更することについては何も言わないので、それによると、CRだけでなく、データ内の完全なCRLFを読み取る必要があります。
更新: 私はすでにこの問題を回避し、データを読み取る独自の方法を実装しましたが、私の質問はまだ次のとおりです:ReadLine
缶に書かれていることをなぜしなかったのですか?