以前作成したMyDataTableクラスを修正し、CSVファイルを正しく扱えるようにしました。 先ほどと同じCSVファイルを読み込ませると次のような表示になります。
CSVファイルではデータに改行文字を含める事もできますが、DataGridViewはデータの中の改行コードを無視されてしまいます。

スクリプト本体は次のようになりました。
a09_filedialog.ipyファイル
# 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クラスの修正個所は次の通りです。
変更前:loadCSVメソッド処理の抜粋
...
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
...
変更後:loadCSVメソッド処理の抜粋
...
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を使うこともできます。
CSVファイル: a10_readfile.csv
name,age,address "yasu,裕",20,AizuWakamatsu abe,25,"Yokohama Aoba-ku"
decodeを使った例:a10_readfile.ipy
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でも正しく指定すれば大丈夫なようです。
テキストファイルから読み込んだ文字列をラベルとコマンドプロンプトに出力するスクリプト:a11_readline_decode.utf8.ipy
# 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.