.net - 如何知道流是 xlsx 或 xls 或 csv?
问题描述
我知道文件扩展名可以知道它,例如:
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
可以查找的流中(但这可能需要很多时间);或实现您自己的流,它将buffer
在读取原始流之前提供内容;或者只是确保在读取流的其余部分之前使用缓冲区。
推荐阅读
- java - 在内存android studio中保存字符串/ EditText
- c - C无法将函数指针类型识别为相同
- javascript - 查找重复项并将其替换为具有相同索引位置的新数组
- java - 验证不工作 Spring Boot,Spring in Action 练习
- oracle - 通过过程更新 Oracle 主表中第二个表的列
- python - python - 根据列值重复pandas DataFrame中的行,并在每个重复行中添加1天
- go - 如何在模型中获取用户输入以在 Beego 中构建查询
- c# - 如果使用 Linq 和实体框架的数据库中已经存在用户名,如何将值更新 1
- maven - 是否可以使用 Maven 和 Junit 5 从 yaml 资源中获取配置文件属性?
- c++ - 无法将字符串转换为浮点数