🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

2回答

869閲覧

csvデータの読み込み時に、もらったデータだけ取り込むことができないです。

jijijias

総合スコア6

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

0グッド

0クリップ

投稿2019/09/16 23:44

csvデータ読み込み時に、あるデータだけ取り込むことができないです。

Visual Studio2017を用いてC#を使って、在庫データを取り込みExcelに在庫管理表
を出力するシステムを作っています。
その際に、日ごとで在庫データを取り込み、その都度在庫管理表を更新していく
システムを作りたいです。

上記の機能を実装中に他のデータであればできていたcsvデータの取り込みが
自分以外の人からもらったデータで行うとエラーがでてしまうようになりました。

該当のソースコード

public int CSVデータを取り込む(string PATH, ds在庫 ds)
{
int N = 0;
StreamReader str = new StreamReader(PATH, Encoding.GetEncoding(932));
string[] stb;
stb = str.ReadLine().Split(',');
while (str.Peek() != -1)
{
stb = str.ReadLine().Split(',');

string 発行番号 = stb[5]; string 抽出1 = "発行番号='" + 発行番号 + "'"; 抽出1 += " AND 指定日='" + DateTime.Parse(stb[3]).ToShortDateString() + "'"; DataRow[] rows = ds.出庫.Select(抽出1); if (rows.Length == 0) { DataRow row = ds.出庫.NewRow(); row["受注者"] = stb[0]; row["便"] = stb[2]; row["指定日"] = DateTime.Parse(stb[3]).ToShortDateString(); row["発行番号"] = stb[5]; 追加する(row, ds); N++; } } str.Close(); return N; }

エラーメッセージ

型 'System.FormatException' のハンドルされていない例外が mscorlib.dll で発生しました
追加情報: 文字列は有効な DateTime ではありませんでした。

扱っているデータ


上部にヘッダーがあり、このようなデータが1820行ある中一行以上消すだけで正常に動きました。

試したこと

もらったデータのどの行でも、一行以上削除すると正常にcsvデータの取り込みをしてくれました。
また、csvデータの中の一行を削除すると70KBほど容量が減るのも何か問題があるのでしょうか。
プログラミングが未熟であるため、もしよければ助言を頂きたく思い投稿させていただきました。
どうかよろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/09/17 00:45

ソースコードは ``` と ``` で囲ってください。インデントされて見やすくなりますので。(``` はバッククォート 3 つです) インデントされてないコードは質問者さん自身も読む気がしないのでは? 閲覧者・回答者はなおさらです。
guest

回答2

0

ベストアンサー

一行削除して保存することにより、不正な CSV が保存するのに使ったソフトによって正しい CSV に直されているのではないかと思います。
そのデータを開いて削除せず上書き保存してみてください。

投稿2019/09/17 00:13

Zuishin

総合スコア28669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

質問に書かれたコードを見ると、ファイルを一行ずつ読んで文字列を作り、String.Split メソッドでその文字列を区切るといった方法を取っているようですね。

改行コードやデリミタ(コンマのような区切り文字)がフィールド値の中にあったり、改行コードが異なったりする場合、そのようは方法は使えないと思いますが、そこは問題ないのですか?

自分以外の人からもらったデータで行うとエラーがでてしまうようになりました。

とのことですが、自分以外の人からもらったデータは上記のような(改行コードやデリミタがフィールド値の中にあるなど)今のコードで対応できないということはありませんか?

【追記】

改行コードやデリミタがフィールド値の中にある場合、フィールド値をダブルクォート (") で囲むと言った約束を設けて対応するそうです。詳しくは以下の記事を見てください。

CSV形式のファイルをDataTableや配列等として取得する
http://dobon.net/vb/dotnet/file/readcsvfile.html

もし、「自分以外の人からもらったデータ」がそのようになっているとすると、上の記事にあるいくつかの約束に対応できるコードを自力で書くのは簡単ではありません。

上に紹介した記事にもありますが、JET とか TextFieldParser など既存の CSV パーサーを使うことを検討されるのが良いと思います。

投稿2019/09/17 00:54

編集2019/09/17 01:33
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2019/09/17 01:07

私もその可能性を一番に考えましたが、どの行でも関係なく一行削除すれば正常に読み込めるようになること、それによってファイルサイズが大きく変わることから、エンコーディングが違うのではないかと思いました。質問のコードではエンコーディングを Shift_JIS に決め打ちしていますが、もらった CSV は UTF-16 の可能性があります。
退会済みユーザー

退会済みユーザー

2019/09/17 01:13

質問者さんが使っている StreamReader(PATH, Encoding.GetEncoding(932)); は BOM がついているとそれで文字コードを判定し、BOM が付いていないと第 2 引数の Encoding で読み込むはずです。なので、UTF-16 なら、たぶん BOM はついているはずなので、大丈夫ではないかと思うのですが。
退会済みユーザー

退会済みユーザー

2019/09/17 01:15

なので、Zuishin さんが指摘された、 > 一行削除して保存することにより、不正な CSV が保存するのに使ったソフトによって正しい CSV に直されているのではないかと思います。 が当たっているのではないかと思います。
Zuishin

2019/09/17 01:18

> StreamReader(PATH, Encoding.GetEncoding(932)); は BOM がついているとそれで文字コードを判定し、BOM が付いていないと第 2 引数の Encoding で読み込むはずです。 こんな仕様だったんですね。知りませんでした。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問