以前作成したMyDataTableクラスを修正し、CSVファイルを正しく扱えるようにしました。 先ほどと同じCSVファイルを読み込ませると次のような表示になります。
CSVファイルではデータに改行文字を含める事もできますが、DataGridViewはデータの中の改行コードを無視されてしまいます。
スクリプト本体は次のようになりました。
# coding=Shift_JIS # @author: YasuhiroABE <yasu@yasundial.org> # from a09_lib import * form = MyForm("Hello World!") ## csv filename filedialog = MyOpenFileDialog() filename = filedialog.open() ## setup datatable dt = MyDataTable() dt.loadCSV(filename) ## setup layout datagridview = MyDataGridView() datagridview.DataSource = dt form.Controls.Add(datagridview) form.run()
MyDataTableクラスの修正個所は次の通りです。
... def loadCSV(self, filename): reader = StreamReader(filename) cols = [] for c in reader.ReadLine().split(","): self.Columns.Add(c, System.Type.GetType("System.String")) cols.append(c) pass l = reader.ReadLine() while(l != None): row = self.NewRow() counter = 0 for item in l.split(","): row[cols[counter]] = item counter += 1 self.Rows.Add(row) l = reader.ReadLine() pass reader.Close() pass pass ...
... def loadCSV(self, filename): parser = MyCSV(filename) cols = [] rownum = 0 for r in parser.eachRow(): tablerow = None itemnum = 0 for item in r.eachItem(): if rownum == 0: self.Columns.Add(item, System.Type.GetType("System.String")) cols.append(item) else: if tablerow is None: tablerow = self.NewRow() tablerow[cols[itemnum]] = item pass itemnum += 1 pass rownum += 1 if tablerow is not None: self.Rows.Add(tablerow) pass pass pass ...
元々は1行目をヘッダと認識して別に処理を行なっていましたが、作成したMyCSVクラスは効率化のためにyield文を使っているため1行だけの処理を抜き出すのが難しくなっています。
特別なメソッドを準備しようかとも思いましたが、とりあえず呼び出し側でカラム、行の数を数えるカウンターを準備する事で回避しています。
今回作成したmycsv.pyライブラリファイルの内容は次の通りです。
# coding=Shift_JIS # @author: YasuhiroABE <yasu@yasundial.org> # import clr clr.AddReferenceByPartialName("Microsoft.VisualBasic") import Microsoft from Microsoft.VisualBasic.FileIO import TextFieldParser from Microsoft.VisualBasic.FileIO import FieldType import System class MyRow: def __init__(self, row): self.row = row pass def eachItem(self): for item in self.row: yield item pass pass def getItem(self): return self.row pass class MyCSV: def __init__(self, filename): self.parser = TextFieldParser(filename, System.Text.Encoding.GetEncoding("Shift_JIS")) self.parser.TextFieldType = FieldType.Delimited self.setDelimiters(',') pass def setDelimiters(self, delimiter): self.parser.SetDelimiters(delimiter) pass def eachRow(self): array = self.parser.ReadFields() while(array): row = MyRow(array) yield row array = self.parser.ReadFields() pass pass pass
行のデータにアクセスする時にはyieldするのが良いとは限らないので、getItem()メソッドを準備しています。
このクラスはCSVファイルの各列のデータは全て文字型だと仮定しています。 これはCSVファイルのエンコーディングを保持する限りは正しい仮定ですが、IronPythonで日本語を正しく扱うためには少し設定が必要です。
coding行と揃っていれば、Shift_JISでもUTF-8でもスクリプトに直接記述した文字をコントロールに表示させる事は可能です。 MyCSVクラスでは.NETの機能を使って、CSVファイルがShift_JISエンコーディングの前提で読み取っています。
単純にファイルの内容を1行づつ表示させるような処理であれば、decodeを使うこともできます。
name,age,address "yasu,裕",20,AizuWakamatsu abe,25,"Yokohama Aoba-ku"
f = open("a10_readfile.csv") for line in f: print line.decode("Shift_JIS")
IronPython 1.xの頃の解説を読むとコマンドプロンプトに出力される文字が化けてしまうのを避けるために"sys.setdefaultencoding()"を使っていたようですが、いまはそんな名前のメソッドはsysモジュールにはありません。
ファイルから読み込んだ文字列をコマンドプロンプトやGUIに渡したい場合には、ファイルのエンコーディングと同じエンコーディングをdecodeメソッドに渡せば扱えるようです。 ファイルはUTF-8でもShift-JISでも正しく指定すれば大丈夫なようです。
# encoding: UTF-8 # @author: YasuhiroABE <yasu@yasundial.org> # import System import clr clr.AddReference("System.Windows.Forms") from System.Windows.Forms import * clr.AddReference("System.Drawing") from System.Drawing import * form = Form() form.Size = Size(240,100) label = Label() label.Size = form.Size f = open("a11.utf8.txt") for line in f: print line.decode('utf8') label.Text += line.decode('utf8') form.Controls.Add(label) Application.Run(form)
確認のためだけなので横着をしてライブラリは使わずにスクリプトを組み立てました。
スクリプトを変更し、"all.sjis.txt"を読み込みline.decode('Shift_JIS')
で変換しても同じ結果が得られます。
Created: 2010-03-13, Last modified: 2010-03-19
www.yasundial.org by Yasuhiro ABE is licensed under a Creative Commons Attribution 2.1 Japan License. Permissions beyond the scope of this license may be available at http://www.yasundial.org/info/license.html.