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

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

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

LibreOffice Calcは、様々なOSで利用可能なオフィススイートであるLibreOfficeに含まれるオープンソースの表計算ソフトです。テンプレートや背景色、枠線といった書式設定の各項目を柔軟で設定することができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

1回答

819閲覧

ロシア語で書かれているdbfファイルを開きたいが文字化けする

Yukiya025

総合スコア86

LibreOffice Calc

LibreOffice Calcは、様々なOSで利用可能なオフィススイートであるLibreOfficeに含まれるオープンソースの表計算ソフトです。テンプレートや背景色、枠線といった書式設定の各項目を柔軟で設定することができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

2クリップ

投稿2018/10/23 07:38

編集2018/10/24 03:52

こんにちは! Вавилонская башняzaliznia.exeのDBFファイルを開きたいです。
Windows7でDBFファイルを落として、LinuxのLibreOfficeで開くのですが、文字化けしています。

このDBFファイルにはロシア語の格変化を判定するためのデータが収められているはずなので、ロシア語の文字コードで開ければ良いはずなのですがUTF-8Cyrillicなんとかの文字コードを選択しても文字化けがなおりません。

開ける前に文字コードを判定する方法はあるのでしょうか。またはPythonを使って中身を見たりデータにアクセスする方法はあるでしょうか。できればLibreOfficeで開いてファイル全体を見たいです。

よろしくお願いしますorz

文字化け画像など

こんな感じで文字化けします。ちなみに、提示されているすべての文字コードを試しましたが、まともに表示してくれたものはありませんでした。
OpenWith

Text Garbling

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

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

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

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

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

ikedas

2018/10/24 01:07

「LinuxのLibreOfficeで開く」というのは具体的にどのような操作をしたのかをお書きください。また、「文字化けしています」とのことであれば、どのように文字化けしているのかスクリーンキャプチャなどで示していただけるとありがたいです。
Yukiya025

2018/10/24 03:49

ikedas様、質問ありがとうございます(≧▽≦) >「LinuxのLibreOfficeで開く」 dbfファイルを右クリックして、"Open With LibreOffice Calc"で開きます。
guest

回答1

0

ベストアンサー

調べたことを書きます。

ファイルを調べる

まず、zaliznia.dbfの中身を調べることにしました。これはどうやらdBASEのデータベースファイルらしいので、ファイルフォーマットの仕様を探して読みました。たとえばここにあります。

odを使ってファイルの中身をダンプして、仕様とくらべてみました。dBASE IIIの形式のようですが、ところどころ違っています。あと、一緒に配布されているzaliznia.varファイルについては、仕様のどこにも記述がありません。

が、フィールドの定義とレコード長、最初のレコードが格納される位置は仕様に基づいて計算できたので、レコードを読んで出力するスクリプトを書いて実行してみました。

bash

1$ python3 zaliznia-2.py zaliznia.dbf 2'\x01\x00\x00\x00\x03\x00' '\t\x00\x00\x00\x15\x00' ' ' 3'#\x00\x00\x00\x03\x00' '+\x00\x00\x00\x15\x00' ' ' 4'E\x00\x00\x00\x05\x00' 'O\x00\x00\x00\x07\x00' ' ' 5'[\x00\x00\x00\x07\x00' 'g\x00\x00\x00\x15\x00' ' ' 6\x00\x00\x00\x02\x00' \x00\x00\x00\x07\x00' ' ' 7\x00\x00\x00\x05\x00' \x00\x00\x00\x07\x00' ' ' 8\x00\x00\x00\x03\x00' '▓\x00\x00\x00\x15\x00' ' ' 9'╠\x00\x00\x00\x01\x00' '╥\x00\x00\x00\x14\x00' \x00\x00\x00\x0e\x00' 10'■\x00\x00\x00\x01\x00' '\x04\x01\x00\x00\x07\x00' ' ' 11'\x10\x01\x00\x00\x01\x00' '\x16\x01\x00\x00\x07\x00' ' ' 12'"\x01\x00\x00\x01\x00' '(\x01\x00\x00\x1a\x00' ' ' 13'G\x01\x00\x00\x07\x00' 'S\x01\x00\x00\x05\x00' ' ' 14']\x01\x00\x00\x04\x00' 'f\x01\x00\x00\x1c\x00' ' ' 15\x01\x00\x00\x03\x00' \x01\x00\x00\x07\x00' ' ' 16\x01\x00\x00\x06\x00' \x01\x00\x00\x06\x00' '▒\x01\x00\x00\x10\x00' 17'╞\x01\x00\x00\t\x00' '╘\x01\x00\x00\x07\x00' ' ' 18(以下略)

質問者さんとよく似た文字化けのしかたをしています。つまり、レコードを読めているのは間違いないですが、データを正しく変換できていないようです。

しかし、フィールドの幅が6バイトでは、文法情報などを格納するには短かすぎます。そもそもテキスト型に\x00などがやたらと入っているのは変です。

これはテキストデータではなく、数値のような固定長データだと思ったほうがよさそうです。そう思ってよく見ると、各フィールドは6バイトのうち、前の4バイトと後の2バイトに分けられるようです。なので、それぞれを整数として出力してみました (後に0x00が詰められることから、リトルエンディアンで格納されていると仮定しました)。

bash

1$ python3 zaliznia-3.py zaliznia.dbf 2[1, 3] [9, 21] None 3[35, 3] [43, 21] None 4[69, 5] [79, 7] None 5[91, 7] [103, 21] None 6[129, 2] [136, 7] None 7[148, 5] [158, 7] None 8[170, 3] [178, 21] None 9[204, 1] [210, 20] [235, 14] 10[254, 1] [260, 7] None 11[272, 1] [278, 7] None 12[290, 1] [296, 26] None 13[327, 7] [339, 5] None 14[349, 4] [358, 28] None 15[391, 3] [399, 7] None 16[411, 6] [422, 6] [433, 16] 17[454, 9] [468, 7] None 18(以下略)

きれいな結果が出ました。それぞれのフィールドのうち前の値は、他のフィールドやレコードの値と重複がなく、はっきりした規則性をもって増加しています。

フィールドごとの値は、まだ見ていないzaliznia.varファイルの中の位置と長さを表していると思われます。これを確認するために、たとえば、上の8番目のレコードの値に従って次を実行してみると、

bash

1$ dd bs=1 skip=204 count=1 if=zaliznia.var 2>/dev/null |iconv -fcp866 -tutf-8 2а 3 4$ dd bs=1 skip=210 count=20 if=zaliznia.var 2>/dev/null |iconv -fcp866 -tutf-8 51 (_без удар._) союз 6 7$ dd bs=1 skip=235 count=14 if=zaliznia.var 2>/dev/null |iconv -fcp866 -tutf-8 8ah and butI eh

これは、オンラインで提供されているデータベースの検索結果と一致します。

Starling databaseについて

ここまで調べたあとで、サイトにあった解説をみつけ、このサイトで使われているのはStarling Databaseというものだと知りました。dBASEを元に拡張されたファイル形式だそうです。

名前が分かったので、GitHubにある資料も見つけることができました。Starlingファイル形式についての解説文書もあったので、ここまで試したことはほぼ間違いないことがわかりました (なお、文字コードはcp866に改変を加えた独自のものを使っているようです)。

Pythonでの方法

上でzaliznia.dbfの内容を出力するために作ったスクリプトを貼っておきます。上の解説を読んで必要な処理を追加すれば、zaliznia.varから実データを読み出すこともできるようになるでしょう。

python

1#-*- python -*- 2 3import sys 4from struct import calcsize, unpack 5 6''' 7最初のレコードのオフセット。 8ファイルによって異なるはずだが、簡単のため決め打ちする。 9オフセットの求めかたはdBASE IIIかStarlingの仕様を参照。 10''' 11initial_offset = 0x82 12''' 13レコードの形式。 14先頭のフラグ1バイトのあとに、カラムの値がパックされて格納される。 15レコードの構成はファイルによって異なるはずだが、簡単のため決め打ちする。 16''' 17record_format = 'B 6s 6s 6s' 18 19def read_records (ioh): 20 ''' 21 IOからレコードを読んで返すジェネレータ関数。 22 ''' 23 record_size = calcsize(record_format) 24 25 ioh.seek(initial_offset) 26 while 1: 27 buf = ioh.read(record_size) 28 if not buf or len(buf) < record_size: 29 break 30 31 flag, word, gram, tran = unpack(record_format, buf) 32 if flag == 0x1A: # 終了 33 break 34 if flag == 0x2a: # 削除されたレコードはとばす 35 continue 36 elif flag != 0x20: 37 raise ValueError('Unknown flag %r' % flag) 38 39 # yield word, gram, tran 40 # yield word.decode('cp866'), gram.decode('cp866'), tran.decode('cp866') 41 yield unpack_ref(word), unpack_ref(gram), unpack_ref(tran) 42 43def unpack_ref(col): 44 ''' 45 VARファイルへの参照値を [オフセット, 長さ] の形式にして返す。 46 Starling仕様参照。 47 ''' 48 if col == b' ': 49 return None 50 else: 51 return list(unpack('<LH', col)) 52 53def main(): 54 ioh = open(sys.argv[1], 'rb') 55 for row in read_records(ioh): 56 # print('%-27r %-27r %r' % row) 57 print('%-16r %-16r %-16r' % row) 58 59if __name__ == '__main__': 60 main()

投稿2018/10/25 05:19

編集2018/10/25 08:50
ikedas

総合スコア4335

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

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

Yukiya025

2018/10/25 08:10

ikedasさま、ありがとうございます(≧▽≦) > zaliznia.varから実データ な、なるほど(゚д゚) 実データが入っているのは.varの方なのですか。。。
ikedas

2018/10/25 10:39

> 必要な処理を追加すれば、zaliznia.varから実データを読み出すこともできる 必要なヒントはすべて回答に入れましたから、よく読んで理解すればできますよ❤️
Yukiya025

2018/11/02 01:46 編集

手持ちのWin7PCを開き、紹介してくださったWindows用のソフト (GitHubにあったもの)で開けました! ありがとうございました❤
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問