【问题标题】:CSVReader throwing error at the last row last columnCSVReader 在最后一行最后一列抛出错误
【发布时间】:2014-07-28 07:31:03
【问题描述】:

我在我的项目中使用 CSVReader 来读取 Windows 服务中的 .csv 文件。 我们将 .csv 文件传递​​给 CSVReader 以处理文件,它工作正常。 但最近我们决定将 csv 文件保存到数据库表并从那里读取。 当用户提交 csv 文件进行处理时,我们的 aspx 页面将读取 csv 文件 并将其转换为字节数组并将其保存到数据库中。 服务将读取表并获取字节数组并将其转换为 Filestream。 此流被传递给 CSVReader 以进行进一步的工作。 现在它为最后一行最后一列抛出错误。 它仅在保存并从数据库中读取后才会发生。 我收到以下错误。 不知道如何解决这个问题。

“CSV 在位置 '494' 的记录 '9' 字段 '3 附近似乎已损坏。当前原始数据:'

听到的是密码 将文件转换为字节数组.....

try
{
     fs = new FileStream(filepath, FileMode.Open);
     fsbuffer = new byte[fs.Length];
     fs.Read(fsbuffer, 0, (int)fs.Length);
}

从数据库读取到字节数组......

myobject.FileByteArray = ObjectToByteArray(row);

public byte[] ObjectToByteArray(DataRow row)
        {
            if (row["fileBytearray"] == null)
                return null;
            try
            {
                BinaryFormatter bf = new BinaryFormatter();
                System.IO.MemoryStream ms = new System.IO.MemoryStream();

                bf.Serialize(ms, row["fileBytearray"]);
                return ms.ToArray();
            }
    }

Stream fileStream = new MemoryStream(myobject.FileByteArray)
using (CsvReader csv = 
                        new CsvReader(new StreamReader(fileStream, System.Text.Encoding.UTF7), hasHeader, ','))

【问题讨论】:

  • 您存储数据的列类型是什么?
  • 列类型为 varbinary (max)
  • 所以不是截断。创建 StreamReader 时,您使用的是UTF7 编码。你确定这是文件最初的编码方式吗?你试过ASCIIUTF8吗?
  • 我不知道文件最初是如何编码的。如何找到文件的编码是什么?我尝试使用 ASCII 和 UTF8 仍然是同样的问题

标签: c# csv filestream


【解决方案1】:

我无法重新创建您的问题,因此,由于没有看到从头到尾的保存和加载,我建议尝试以下方法进行检索:

public MemoryStream LoadReportData(int rowId)
{

  MemoryStream stream = new MemoryStream();

  using (BinaryWriter writer = new BinaryWriter(stream))
  {

    using (DbConnection connection = db.CreateConnection())
    {
      DbCommand selectCommand = "SELECT CSVData FROM YourTable WHERE Id = @rowId";

      selectCommand.Connection = connection;

      db.AddInParameter(selectCommand, "@rowId", DbType.Int32, rowId);
      connection.Open();

      using (IDataReader reader = selectCommand.ExecuteReader(CommandBehavior.SequentialAccess))
      {

        while (reader.Read())
        {

          int startIndex = 0;
          int bufferSize = 8192;

          byte[] buffer = new byte[bufferSize];

          long retVal = reader.GetBytes(0, startIndex, buffer, 0, bufferSize);

          while (retVal == bufferSize)
          {

            writer.Write(buffer);
            writer.Flush();

            startIndex += bufferSize;
            retVal = reader.GetBytes(0, startIndex, buffer, 0, bufferSize);

          }

          writer.Write(buffer, 0, (int)retVal);
        }

      }

    }
  }

  return stream;

}

您需要将 selectCommand sql 和参数替换为您用于返回数据的任何 sql。

此方法使用SqlDataReader 从适当的行(在我的示例中由 rowId 标识)和列(在我的示例中称为 CSVData)顺序读取字节,这应该避免在输出时出现任何截断问题(它可以是您的 DataTable 对象仅返回第一个 n 字节)。 MemoryStream 对象可用于将 CSV 文件重新保存到文件系统进行测试,或直接输入到您的 CSVReader。

如果您可以发布您的 Save 方法(您实际上将数据保存到数据库中),那么我们也可以检查该方法以确保那里也不会发生截断。

我现在可以提出的另一个建议是将文件加载到byte 数组中。如果你打算一次性加载文件,那么你可以简单地替换:

try
{
     fs = new FileStream(filepath, FileMode.Open);
     fsbuffer = new byte[fs.Length];
     fs.Read(fsbuffer, 0, (int)fs.Length);
}

byte[] fileBytes = File.ReadAllBytes(filepath);

【讨论】:

  • 感谢您的详细解释并给我代码。真的很感谢你的时间。它解决了这个问题。
猜你喜欢
  • 2013-02-19
  • 2017-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多