我知道文件扩展名可以知道它,例如:
void Main()
{
Console.WriteLine(GetExcelType("xxx.xls")); // Xls
Console.WriteLine(GetExcelType("xxx.xlsx")); // Xlsx
Console.WriteLine(GetExcelType("xxx.csv")); // csv
}
// You can define other methods, fields, classes and namespaces here
internal enum ExcelType
{
Xlsx,Xls,Csv
}
internal ExcelType GetExcelType(string path)
{
var e = Path.GetExtension(path).ToLowerInvariant();
switch (Path.GetExtension(path).ToLowerInvariant())
{
case ".csv":
return ExcelType.Csv;
case ".xlsx":
return ExcelType.Xlsx;
case ".xls":
return ExcelType.Xls;
default:
throw new InvalidOperationException("Only allow file extension xlsx,xls,csv");
}
}
但如果输入是 Stream,则没有要检查的文件扩展名。
最佳答案
您可以读取流的几个字节并猜测格式。
var buffer = new byte[512];
stream.Read(buffer, 0, buffer.Length);
var magic = BitConverter.ToUInt32(buffer, 0);
switch (magic)
{
// Old office format (can be any office file)
case 0xE011CFD0: return ExcelType.Xls;
// New office format (can be any ZIP archive)
case 0x04034B50: return ExcelType.Xlsx;
}
// Text file (the bigger the buffer, the more probability)
// Won't work for UTF-16 encoding, but it's rare
if (buffer.All(b => b >= ' ' || b == '\n' || b == '\r' || b == '\t')) return ExcelType.Csv;
throw new InvalidOperationException();
当然,这只是一个猜测,并不能保证流确实是预期的格式,但文件扩展名也不提供任何保证。确保输入格式正确的唯一方法是完全解析它并处理可能发生的任何异常。但这个猜测足以选择尝试哪个解析器。
此外,这还会消耗流中的字节,因此如果您要在检查后使用流,则需要考虑到这一点。如果stream.CanSeek == true
,则只需设置stream.Position = 0
即可。如果不是,您可以将原始流复制到可以查找的 MemoryStream
中(但这可能需要很多时间);或者实现您自己的流,它将在读取原始流之前提供缓冲区的内容;或者只是确保在读取流的其余部分之前使用缓冲区。
关于.net - 如何知道流是xlsx、xls还是csv?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66731497/