challenge 固定長データ

固定長のデータが記載されたファイルを読み込むプログラムを作成してください。読み込んだデータは、複数の値を格納できるデータ型に格納してください。

ファイルには、すべて ascii 文字で以下のデータが格納されています。デリミタはなく、固定長で格納されています。レコードとレコードのあいだも改行はありません。

  1. 姓 (12文字) 文字数が足りない場合は、後ろを空白で埋めてあります。
  2. 名 (12文字) 文字数が足りない場合は、後ろを空白で埋めてあります。
  3. 性別 (F,M,Uの3種類、1文字)
  4. 年齢 (3桁の数字、桁数が足りない場合は、ゼロで埋めず、頭を空白で埋めてあります。
  5. 年 2008 固定
  6. 月 03 固定
  7. さらに以下のデータが日付分くりかえされます。
    1. 日付 (01 〜 31) 2文字
    2. 朝食のメニュー (500文字)
    3. 昼食のメニュー (500文字)
    4. 夕食のメニュー (500文字)

以上の形式のデータ500人分を読みこんで、データを複数の値を格納できるデータ型に格納してください。データに大して何か処理を行う必要はなく、すぐに破棄してかまいません。

この問題は、このようなファイルをどのように扱うかを知りたくて作成しました。

Posted feedbacks - C#

投稿速さ重視で
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
using System;
using System.Collections.Generic;
using System.IO;
struct MenuList
{
    public string Day;
    public string Firstbread;
    public string Lunch;
    public string Dinner;
}

struct Record
{
    public string FirstName;
    public string SecondName;
    public string Sex;
    public string Age;
    public string Year;
    public string Month;
    public List<MenuList> Menu;
}

class Program
{
    static void Main(string[] args)
    {
        List<Record> meibo = new List<Record>();

        //テストデータ作成
        using (StreamWriter sw = new StreamWriter(@"C:\testdata.txt"))
        {
            for (int i = 0; i < 500; i++)
            {
                sw.Write("{0, -12}", "Yamada");
                sw.Write("{0, -12}", "Tarou");
                sw.Write("{0,   1}", "M");
                sw.Write("{0,   3}", "26");
                sw.Write("{0,   4}", "2008");
                sw.Write("{0,   2}", "03");
                for (int j = 1; j <= 31; j++)
                {
                    sw.Write("{0:00}", j);
                    sw.Write("{0,-500}", "Yamada");
                    sw.Write("{0,-500}", "Yamada");
                    sw.Write("{0,-500}", "Yamada");
                }
            }
            sw.Dispose();
        }


        using (StreamReader sr = new StreamReader(@"C:\testdata.txt"))
        {
            Record temp;
            while (!sr.EndOfStream)
            {
                temp = new Record();
                char[] buffer;
                
                //性
                buffer = new char[12];
                sr.Read(buffer, 0, buffer.Length);
                temp.FirstName = string.Format("{0:s12}", new string(buffer));

                //名
                buffer = new char[12];
                sr.Read(buffer, 0, buffer.Length);
                temp.SecondName = string.Format("{0:s12}", new string(buffer));

                //性別
                buffer = new char[1];
                sr.Read(buffer, 0, buffer.Length);
                temp.Sex = string.Format("{0:s1}", new string(buffer));

                //年齢
                buffer = new char[3];
                sr.Read(buffer, 0, buffer.Length);
                temp.Age = string.Format("{0,3:s3}", new string(buffer));
                
                //年
                buffer = new char[4];
                sr.Read(buffer, 0, buffer.Length);
                temp.Year = string.Format("{0:s4}", new string(buffer));

                //月
                buffer = new char[2];
                sr.Read(buffer, 0, buffer.Length);
                temp.Month = string.Format("{0:s2}", new string(buffer));

                //ループ
                temp.Menu = new List<MenuList>();
                for (int i = 1; i <= 31; i++)
                {
                    MenuList temp2 = new MenuList();
                    //日
                    buffer = new char[2];
                    sr.Read(buffer, 0, buffer.Length);
                    temp2.Day = string.Format("{0:s2}", new string(buffer));

                    //朝食
                    buffer = new char[500];
                    sr.Read(buffer, 0, buffer.Length);
                    temp2.Firstbread = string.Format("{0:s500}", new string(buffer));

                    //昼食
                    buffer = new char[500];
                    sr.Read(buffer, 0, buffer.Length);
                    temp2.Lunch = string.Format("{0:s500}", new string(buffer));


                    //夕食
                    buffer = new char[500];
                    sr.Read(buffer, 0, buffer.Length);
                    temp2.Dinner = string.Format("{0:s500}", new string(buffer));

                    temp.Menu.Add(temp2);
                }

                meibo.Add(temp);
            }

            foreach (Record result in meibo)
            {
                Console.WriteLine("FirstName : {0}", result.FirstName);
                Console.WriteLine("SecondName : {0}", result.SecondName);
                Console.WriteLine("Sex : {0}", result.Sex);
                Console.WriteLine("Age : {0}", result.Age);
                Console.WriteLine("Year : {0}", result.Year);
                Console.WriteLine("Month : {0}", result.Month);
                foreach (MenuList result2 in result.Menu)
                {
                    Console.WriteLine("Day : {0}", result2.Day);
                    Console.WriteLine("Firstbread : {0}", result2.Firstbread);
                    Console.WriteLine("Lunch : {0}", result2.Lunch);
                    Console.WriteLine("Dinner : {0}", result2.Dinner);
                }
            }
            sr.Dispose();
        }
    }
}

Microsoft.VisualBasic.FileIO.TextFieldParserってとっても便利なんですよ~、と書いてみたら、
TextFieldParserはレコードの区切りに改行がないと駄目なようです。
てことで、とても無理やりなコードになりました。

テストデータの生成にtenkaさんの#6079のコードの一部を頂きました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//http://ja.doukaku.org/170/ 投稿用
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.VisualBasic.FileIO;

namespace どう書く_org固定長デ {
    class Program {
        static void Main(string[] args) {       
            ////テストデータ作成
            //using(StreamWriter sw = new StreamWriter(@"C:\testdata.txt")) {
            //    for(int i = 0; i < 500; i++) {
            //        sw.Write("{0, -12}", "Yamada");
            //        sw.Write("{0, -12}", "Tarou");
            //        sw.Write("{0,   1}", "M");
            //        sw.Write("{0,   3}", "26");
            //        sw.Write("{0,   4}", "2008");
            //        sw.Write("{0,   2}", "03");
            //        for(int j = 1; j <= 31; j++) {
            //            sw.Write("{0:00}", j);
            //            sw.Write("{0,-500}", "Yamada");
            //            sw.Write("{0,-500}", "Yamada");
            //            sw.Write("{0,-500}", "Yamada");
            //        }
            //    }
            //    sw.Dispose();
            //}

            //ファイル読み込み
            StreamReader sr = new StreamReader(@"C:\testdata.txt");
            StringBuilder sb = new StringBuilder(sr.ReadToEnd());

            //フィールドの幅の配列を作成
            int recordLength = 0;
            List<int> fieldWidths = new List<int>();
            fieldWidths.AddRange(new int[] { 12, 12, 1, 3, 4, 2 });
            for(int i = 0; i < 31; i++) {
                fieldWidths.AddRange(new int[] { 2, 500, 500, 500 });
            }
            foreach(int i in fieldWidths) {
                recordLength += i;
            }

            TextFieldParser tfp = getTfp(fieldWidths.ToArray(), sb.ToString().Substring(0, recordLength));
            List<Record> Table = new List<Record>();
            
            while(!tfp.EndOfData) {
                string[] fields = tfp.ReadFields();
                Record record = new Record() {
                    LastName = fields[0],
                    FirstName = fields[1],
                    Sex = fields[2],
                    Age = fields[3],
                    Year = fields[4],
                    Month = fields[5],
                    MenuList = new List<DayMenu>()
                };
   
                for(int i = 6; i < fields.Length; i = i + 4) {
                    record.MenuList.Add(new DayMenu() {
                        Day = fields[i],
                        Firstbread = fields[i + 1],
                        Lunch = fields[i + 2],
                        Dinner = fields[i + 3],
                    });
                }
                Table.Add(record);
                sb.Remove(0, recordLength);
                if(sb.Length == 0) break;
                tfp = getTfp(fieldWidths.ToArray(), sb.ToString(0, recordLength));
            }
            tfp.Close();
        }

        static TextFieldParser getTfp(int[] fieldWidths,string value) {
            TextFieldParser tfp = new TextFieldParser(new StringReader(value));
            tfp.TextFieldType = FieldType.FixedWidth;
            tfp.FieldWidths = fieldWidths;
            return tfp;
        }
    }

    class Record {
        public string LastName { set; get; }
        public string FirstName { set; get; }
        public string Sex { set; get; }
        public string Age { set; get; }
        public string Year { set; get; }
        public string Month { set; get; }
        public List<DayMenu> MenuList { set; get; }
    }

    class DayMenu {
        public string Day { set; get; }
        public string Firstbread { set; get; }
        public string Lunch { set; get; }
        public string Dinner { set; get; }
    }
}

Index

Feed

Other

Link

Pathtraq

loading...