プロが教えるわが家の防犯対策術!

お世話になります。

csvファイルをバイナリ化する手順について教えてください。

※バイナリファイルからの取り出し時において、csv一行あたりの
バイト列長が均一になるようにしたいです。

csvの中身
日付、小数、小数、小数、小数、小数

以上、よろしくお願いいたします。

A 回答 (4件)

> // ↓ここで例外が出る!


> _data = BitConverter.GetBytes(Double.Parse(sb.ToString()));

その例外はDouble.Parseがthrowしてるんじゃないかしら。
sb.ToString()の結果は正当ですか?

この回答への補足

お世話になります。
おかげさまをもちまして、csvファイルから、
バイト列としてファイルに変換する(何故かテキストで読める)ことができました。

> _data = BitConverter.GetBytes(Double.Parse(sb.ToString()));

おっしゃるとおり、マヌケな実装をしてしまいました。すみません。

書き込みの問題はとりあえずクローズさせていただくとして、
読み込み(復元)の段階でうまく行っていないので、
引き続き質問させてください。

下記、CSVDecoder.load でそのファイルからデータを復元しようと思うのですが、
各要素(小数)が思うように取れませんでした。
当方の実装の誤りを指摘していただければ非常にありがたいです。
お忙しいところ恐縮ですが、よろしくお願いいたします。

----------------------------------
Source Code


using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace CSVDataConverter
{

// CSV(binary) -> csv(text)
class CSVDecoder
{
public void load(String _from, String _to)
{
const int RECORD_LENGTH = 128;
const int ELEMENT_LENGTH = 16;
FileStream f_in = null;
byte[] _data = null;
//ディレクトリにあるファイルを取得する
String[] fs = System.IO.Directory.GetFiles(_from, "*", System.IO.SearchOption.AllDirectories);
foreach (String file in fs)
{
f_in = new FileStream(file, FileMode.Open, FileAccess.Read);
_data = new byte[f_in.Length];
f_in.Read(_data, 0, _data.Length);

unsafe
{
double p09 = 0;
double p10 = 0;
double p11 = 0;
double p12 = 0;
double p13 = 0;
double p14 = 0;
double p15 = 0;
double p18 = 0;
fixed (byte* p = &_data[0])
{
for (int offset = 0; offset < _data.Length; offset += RECORD_LENGTH)
{
p09 = *(double*)(p + offset);
p10 = *(double*)(p + ELEMENT_LENGTH + offset);
p11 = *(double*)(p + 2 * ELEMENT_LENGTH + offset);
p12 = *(double*)(p + 3 * ELEMENT_LENGTH + offset);
p13 = *(double*)(p + 4 * ELEMENT_LENGTH + offset);
p14 = *(double*)(p + 5 * ELEMENT_LENGTH + offset);
p15 = *(double*)(p + 6 * ELEMENT_LENGTH + offset);
p18 = *(double*)(p + 7 * ELEMENT_LENGTH + offset);

Console.WriteLine(p09 + ", " + p10 + ", " + p11 + ", " + p12 + ", " + p13 + ", " + p14 + ", " + p15 + ", " + p18);
}
}
Console.WriteLine("----------");
}
}
return;
}
}
class Program
{
static void Main(string[] args)
{
if (args.Length != 3)
{
Console.WriteLine("[Error:1] SYNOPSIS : CSVDataConverter <src_dir> <dst_dir> <-encode|-decode>");
}
else if(args[2].Equals("-encode"))
{
(new CSVEncoder()).load((String)args[0], (String)args[1]);
}
else if (args[2].Equals("-decode"))
{
(new CSVDecoder()).load((String)args[0], (String)args[1]);
}
else
{
Console.WriteLine("[Error:2] SYNOPSIS : CSVDataConverter <src_dir> <dst_dir> <-encode|decode>");
}
}
}
}

補足日時:2007/11/12 19:47
    • good
    • 1

ANo.2> まぁでも、C#よりC++のほうが楽ですね。

たぶん。

同意します。
.Netで、というならC++/CLIで書いちゃいます僕ならきっと。
    • good
    • 0

日付をlong2つ、小数を8バイト浮動小数点にして突っ込むだけでいいと思いますけど。


まぁでも、C#よりC++のほうが楽ですね。たぶん。

この回答への補足

ご回答ありがとうございます。しかしすみませんが。C#でなければならない事情がございまして、質問を続行させてください。
以下、試験的にd09,d10のみつなげようとしていますが、何千行にも及ぶためか、下記の箇所で例外が出ます。また、BitConverter.ToStringではなく、BitConverter.ToInt** にしても同じ箇所で例外が出ます。おそらく根本のところで当方の書き方が間違っていると思われますので、ご指南いただきたく存じます。よろしくお願いいたします。


// csv 1行分
line = r.ReadLine();
while (line != null)
{
element = line.Split(',');
d09 = Double.Parse(element[9]);
d10 = Double.Parse(element[10]);
d11 = Double.Parse(element[11]);
d12 = Double.Parse(element[12]);
d14 = Double.Parse(element[14]);
d15 = Double.Parse(element[15]);
d18 = Double.Parse(element[18]);

_data = BitConverter.GetBytes(d09);
sb.Append(BitConverter.ToString(_data).Replace("-", ""));
_data = BitConverter.GetBytes(d10);
sb.Append(BitConverter.ToString(_data).Replace("-", ""));
line = r.ReadLine();
}
// ↓ここで例外が出る!
_data = BitConverter.GetBytes(Double.Parse(sb.ToString()));

// バイナリファイル書き込み
f_out = new FileStream(_to + file.Substring(file.Length - 8, 4), FileMode.OpenOrCreate, FileAccess.Write);
BinaryWriter writer = new BinaryWriter(f_out);
f_out.Seek(0x00000000, SeekOrigin.Begin);
writer.Write(_data);

補足日時:2007/11/12 00:20
    • good
    • 0

"バイナリ化"とは何ですか?

この回答への補足

csv → 適当な方式に従ってバイト列(byte[]) → バイナリファイル作成(BinaryWriter)
です。説明が足りなくてすみません。この「適当な方式」についてお聞きしたかったという意味です。

-----

この、「適当な方式」が決まってからの手順はOKなのですが、
上記のcsv(30,000要素/1ファイル 変換対象ファイル数3,000~4,000)の形式が与えられている状況で、「適当な方式に従ってバイト列(byte[]) → バイナリファイル」を作成します。

ちなみに一要素づつbyte[]化して、それを文字列に戻してStringBuilderに順次appendしたものをbyte[]列にしてファイルに書き込もうとしたら例外が出ました。

読み出し側のforループで、作成したバイナリファイルから固定長のバイト列を順次切り出し、各要素を解釈したい場合、どのようにバイト列を作るのが適当か、お聞きしたく存じます。どうぞよろしくお願いいたします。

※ちなみに対象銘柄数の多さから、csvそのままのテキスト処理のみにて行うあるいはDBを用いるなどの方式は、I/O負荷あるいはネットワーク負荷
がかかりそうなのと、リファレンスがネット上にあまりなかったので検討対象から外しています。

補足日時:2007/11/11 09:43
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!