如何在c#中导入和读取大型二进制文件数据?
How to import and read large binary file data in c#?
我有一个包含不同数据类型的大型二进制文件,我可以访问文件中的单个记录,但我不确定如何遍历二进制值并将其逐字节加载到内存流中
我一直在使用二进制 reader
BinaryReader binReader = new BinaryReader(File.Open(fileName, FileMode.Open));
Encoding ascii = Encoding.ASCII;
string authorName = binReader.ReadString();
Console.WriteLine(authorName);
Console.ReadLine();
但这行不通,因为我有一个包含不同数据类型的大文件
简单地说,我需要将文件转换为逐字节读取,然后读取这些数据(无论是字符串还是其他任何形式)。
将不胜感激任何可以帮助的想法
下面是一段简单的代码,展示了最基本的实现方式。
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace binary_read
{
class Program
{
private static readonly int bufferSize = 1024;
static async Task Main(string[] args)
{
var bytesRead = 0;
var totalBytes = 0;
using (var stream = File.OpenRead(args.First()))
{
do
{
var buffer = new byte[bufferSize];
bytesRead = await stream.ReadAsync(buffer, 0, bufferSize);
totalBytes += bytesRead;
// Process buffer
} while (bytesRead > 0);
Console.WriteLine($"Processed {totalBytes} bytes.");
}
}
}
}
要注意的主要位在 using
块内。
首先,在使用 files/streams/sockets 时,最好使用 using
如果可能的话,确定性地清理自己。
那么如果您只需要原始数据,那么只需在 stream
上调用 Read
/ReadAsync
即可。然而,有各种 'readers' 提供了一种抽象,使使用某些格式更容易。
因此,如果您知道要读取整数、双精度数和字符串,那么您可以使用 BinaryReader
和 ReadIntxx/ReadDouble/ReadString 方法。
如果您正在读入一个结构,那么您可以按照上面@JonasH 的建议在循环中读取属性。或者使用this answer.
中的方法
这在很大程度上取决于文件的格式。文件中的每个字节可能代表不同的东西,或者它可能只代表一个大数组中的值,或者两者的某种混合。
您需要知道格式是什么样子才能阅读它,因为二进制文件不是自我描述的。读取一个简单的对象可能看起来像
var authorName = binReader.ReadString();
var publishDate = DateTime.FromBinary(binReader.ReadInt64());
...
如果您有项目列表,通常使用长度前缀。像
var numItems = binReader.ReadInt32();
for(int i = 0; i < numItems; i++){
var title = binReader.ReadString();
...
}
然后,您通常会根据可在应用程序的其余部分中使用的数据创建一个或多个对象。即
new Bibliography(authorName, publishDate , books);
如果这是你无法控制的格式,希望你有一个详细的规范。否则,除了最笨拙的解决方案之外,这都是失败的原因。
如果数据多于内存无法容纳的数据,您需要某种流式处理机制。 IE。读取一个项目,对该项目进行一些处理,保存结果,读取下一个项目等。
如果您确实控制格式,我会建议更易于管理的替代方案。我用过 protobuf.Net,我觉得它很容易使用,但还有其他选择。使用这类库的常用方法是为数据创建一个class,并为应该存储的字段添加属性。该库可以自动管理 serialization/deserialization,通常可以轻松处理继承和格式更改等事情。
我有一个包含不同数据类型的大型二进制文件,我可以访问文件中的单个记录,但我不确定如何遍历二进制值并将其逐字节加载到内存流中
我一直在使用二进制 reader
BinaryReader binReader = new BinaryReader(File.Open(fileName, FileMode.Open));
Encoding ascii = Encoding.ASCII;
string authorName = binReader.ReadString();
Console.WriteLine(authorName);
Console.ReadLine();
但这行不通,因为我有一个包含不同数据类型的大文件 简单地说,我需要将文件转换为逐字节读取,然后读取这些数据(无论是字符串还是其他任何形式)。
将不胜感激任何可以帮助的想法
下面是一段简单的代码,展示了最基本的实现方式。
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace binary_read
{
class Program
{
private static readonly int bufferSize = 1024;
static async Task Main(string[] args)
{
var bytesRead = 0;
var totalBytes = 0;
using (var stream = File.OpenRead(args.First()))
{
do
{
var buffer = new byte[bufferSize];
bytesRead = await stream.ReadAsync(buffer, 0, bufferSize);
totalBytes += bytesRead;
// Process buffer
} while (bytesRead > 0);
Console.WriteLine($"Processed {totalBytes} bytes.");
}
}
}
}
要注意的主要位在 using
块内。
首先,在使用 files/streams/sockets 时,最好使用 using
如果可能的话,确定性地清理自己。
那么如果您只需要原始数据,那么只需在 stream
上调用 Read
/ReadAsync
即可。然而,有各种 'readers' 提供了一种抽象,使使用某些格式更容易。
因此,如果您知道要读取整数、双精度数和字符串,那么您可以使用 BinaryReader
和 ReadIntxx/ReadDouble/ReadString 方法。
如果您正在读入一个结构,那么您可以按照上面@JonasH 的建议在循环中读取属性。或者使用this answer.
中的方法这在很大程度上取决于文件的格式。文件中的每个字节可能代表不同的东西,或者它可能只代表一个大数组中的值,或者两者的某种混合。
您需要知道格式是什么样子才能阅读它,因为二进制文件不是自我描述的。读取一个简单的对象可能看起来像
var authorName = binReader.ReadString();
var publishDate = DateTime.FromBinary(binReader.ReadInt64());
...
如果您有项目列表,通常使用长度前缀。像
var numItems = binReader.ReadInt32();
for(int i = 0; i < numItems; i++){
var title = binReader.ReadString();
...
}
然后,您通常会根据可在应用程序的其余部分中使用的数据创建一个或多个对象。即
new Bibliography(authorName, publishDate , books);
如果这是你无法控制的格式,希望你有一个详细的规范。否则,除了最笨拙的解决方案之外,这都是失败的原因。
如果数据多于内存无法容纳的数据,您需要某种流式处理机制。 IE。读取一个项目,对该项目进行一些处理,保存结果,读取下一个项目等。
如果您确实控制格式,我会建议更易于管理的替代方案。我用过 protobuf.Net,我觉得它很容易使用,但还有其他选择。使用这类库的常用方法是为数据创建一个class,并为应该存储的字段添加属性。该库可以自动管理 serialization/deserialization,通常可以轻松处理继承和格式更改等事情。