質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

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

Visual Basic .NET

Microsoft Visual Basic .NET (VB.NET)とはオブジェクト志向のプログラム言語です。 Microsoft"s Visual Basic 6 のバージョンアップとしてみることができますが、Microsoft.NET Frameworktによって動かされています。

Q&A

解決済

1回答

3439閲覧

c# 固定長(改行区切り)ファイルフォーマットのテキスト出力について

seesaajira-

総合スコア107

C#

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

Visual Basic .NET

Microsoft Visual Basic .NET (VB.NET)とはオブジェクト志向のプログラム言語です。 Microsoft"s Visual Basic 6 のバージョンアップとしてみることができますが、Microsoft.NET Frameworktによって動かされています。

0グッド

0クリップ

投稿2022/04/21 05:08

編集2022/04/21 05:10

他システムとの連携で固定長(改行区切り)ファイルフォーマットのテキスト出力が必要です。

構成は以下が1ブロックになっており
ヘッダ(300Byte)
明細(100Byte) ※複数行あり
トレーラ(50Byte)
各レコードの最後に改行コードが入ります(CR+LF)

StreamWriterで固定長テキストの出力方法が見つからず、
こちらのサイトを参考に
https://www.itlab51.com/?p=1984

以下のようにヘッダ、明細、トレーラの構造体を作成し、
「FileSystem.FilePut」で出力しましたが、
固定長のサイズが「FileSystem.FileOpen」で指定したヘッダデータのサイズになってしまいます。

ヘッダ、明細、トレーラを指定したサイズで出力する方法はございませんでしょうか?
宜しくお願い致します。

C#
.Net Framework 4.7.2を使用しています。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; using Microsoft.VisualBasic; namespace テキストデータ作成 { public class 構造体 { //※見やすくする為、項目を削っています internal struct ヘッダデータ { [VBFixedString(2)] public string タグ; [VBFixedString(10)] public string 伝票番号; [VBFixedString(1)] public string 改行; } internal struct 明細データ { [VBFixedString(2)] public string タグ; [VBFixedString(13)] public string 商品コード; [VBFixedString(2)] public string 伝票行番号; [VBFixedString(50)] public string 商品名称; [VBFixedString(4)] public string 納品数; [VBFixedString(9)] public string 原価金額; [VBFixedString(9)] public string 原単価; [VBFixedString(1)] public string 改行; } internal struct トレーラデータ { [VBFixedString(2)] public string タグ; [VBFixedString(11)] public string 原価金額合計; [VBFixedString(1)] public string 改行; } public struct 出荷データ { public string 伝票番号 { get; set; } ...※その他項目は割愛します } } }
public bool テキスト出力(string ファイルパス, IReadOnlyCollection<構造体.出力データ> 出力データ) { try { 構造体.ヘッダデータ _ヘッダデータ = new 構造体.ヘッダデータ(); 構造体.明細データ _明細データ = new 構造体.明細データ(); 構造体.トレーラデータ _トレーラデータ = new 構造体.トレーラデータ(); FileSystem.FileOpen(1, @ファイルパス, OpenMode.Random, OpenAccess.Default, OpenShare.Default, Strings.Len(_ヘッダデータ)); string _伝票番号 = string.Empty; foreach (構造体.出力データ item in 出力データ) { //伝票番号が変わったらヘッダをテキストに出力 if (_伝票番号 != item.伝票番号) { //トレーラの出力予定 _ヘッダデータ.タグ = "HD"; _ヘッダデータ.伝票番号 = item.伝票番号; _ヘッダデータ.改行 = Environment.NewLine; FileSystem.FilePut(1, _ヘッダデータ); _伝票番号 = item.伝票番号; } _明細データ.タグ = "DT"; _明細データ.商品コード = item.商品コード; _明細データ.伝票行番号 = item.伝票行番号; _明細データ.商品名称 = item.商品名称; _明細データ.納品数量 = item.納品数量; _明細データ.原価金額 = item.原価金額; _明細データ.原単価 = item.原単価; _明細データ.改行 = Environment.NewLine; FileSystem.FilePut(1, _出荷明細データ); } FileSystem.FileClose(1); return true; } catch (Exception) { return false; throw; } finally { } }

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

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

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

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

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

Zuishin

2022/04/21 06:41

VB からの移植ですよね? 元々は動いていたんですか?
seesaajira-

2022/04/21 12:13

いえ、動いていません。 参考にしたサイトのやり方を真似たので、こうなってしまいました。 出力された項目の内容自体は問題なく構造体で指定したサイズで出力されているのですが、 明細データの行のサイズがヘッダデータのサイズで出力されてしまいます。 固定長のテキスト出力は初めてで、 色々参考にしてみましたがどうしてよいか分かりません。 何か良い方法はないかと質問してみました。 なにかアドバイスがありましたらよろしくお願いいたします。
Zuishin

2022/04/21 12:21

そのサイトの真似をやめて素直に Stream.Read を使うのが良いのではと思います。
dodox86

2022/04/22 00:43

私もZuishinさんのご意見に同意します。サイトの記事を参考にすること自体は悪いことではないと思いますが、ご自分で記事内容を消化できない場合、修正や問題の解消は結局他人に依存することになります。よく分からなければまずはSystem.IO.BinaryWriterやSystem.IO.FileStreamクラスを使って、例えばレコードごとにbyte[]配列のイメージで書き込むような方法でやるのが良いと思います。(<それすら分からなければまずファイルの読み書きを自由にできるようになる必要があります) データ中に文字列が存在する場合、どのみちC#のstring(UTF-16)からエンコード/デコードする必要もあります。
seesaajira-

2022/04/22 02:27

Zuishinさん、dodox86さん回答ありがとうございます。 そうですね。System.IO.BinaryWriter等でもう少し考えてみます。 CSVへの書き込みしかやった事なかったので、簡単に考えていました。 固定長のテキスト出力って、私にとっては、なかなか手強いです。
guest

回答1

0

自己解決

とりあえず
StreamWriterを使う方向で直してみました。
列挙体に構造体メンバのサイズ持たせ、
PadRightで文字列の足りない桁数に空白を埋め込むようにして
構造体メンバを1行に合体させ
writelineで出力するようにしたところ
なんとかヘッダ、明細、トレーラの各バイト数でテキスト出力する事ができました。

internal enum ヘッダメンバサイズ { タグ= 2, 伝票番号 =10 }
Encoding _enc = Encoding.GetEncoding("Shift_JIS"); foreach (構造体.出力データ item in 出力データ) { using (StreamWriter sw = new StreamWriter(@ファイルパス, true,_enc)) { _ヘッダデータ.タグ = "HD"; _ヘッダデータ.伝票番号 = パディング(item.伝票番号, (int)列挙体.ヘッダメンバサイズ.伝票番号); sw.WriteLine(ヘッダ行を1行にする(_ヘッダデータ)); //明細行も同様 }
パディング(string value, int メンバサイズ) { Encoding enc = Encoding.GetEncoding("Shift_JIS"); return value.PadRight(メンバサイズ - (enc.GetByteCount(value) - value.Length)); }
string ヘッダ行を1行にする(構造体.ヘッダデータ ヘッダデータ) { string _ヘッダ = _出荷ヘッダデータ.タグ + _出荷ヘッダデータ.伝票番号 +その他項目....+ return _ヘッダ }

投稿2022/04/27 02:18

seesaajira-

総合スコア107

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問