D言語でシャキーン4
さて4回目となりましたD言語で遊ぼうのコーナー。
プログラミングに興味がない人にとってはどうでもいい記事だと思います。
見てる人がいたら「bbキモイ色死ね!」とコメントしてね!
この前までの問題点は…
・D言語の実行ファイルではシフトJISの文字列を引数にとれない
これはwindowsが標準でシフトJISを扱う仕様であることと、D言語が標準でUTF-8を扱う仕様であることが原因です。
これをやっちゃうと「invalid UTF-8 sequence」とかいうエラーが出てメイン関数のしょっぱなで弾かれます。
ゆえに日本語ファイル名を引数にとると処理をすることすらなくエラーでて終了です。致命的です。
これを改善するのが至上命題でした!!!
そこでグーグル先生に聞いてみたら… 既にやってる人がいました。
このサイトを参考にしてがんばってみました。ありがとうございます。
いじったのは…
dmd/src/phobos/win32.mak
dmd/src/phobos/internal/dmain2.d
で、上のサイトを参考にして新たに作成したのは…
dmd/src/phobos/std/mbs.d
です。
上記サイトに書いてあったmbs.dのソースではmakeできなかったので、
・strlen関数を通すためにimport文を追加
・MultiByteToWideChar関数とMultiByteToWideChar関数の型が間違ってたのでそれぞれに.ptrを追加
しました。
そんでもって
make -f win32.mak
make -f win32.mak install
したらmbsがライブラリに加わったらしく使えるようになってて、dmain2.dも通りました。
これにより!dの実行ファイルではinvalid~が出なくなったのです!!!うれしいわ!!
そこで今回のソースは
bbzipAlpha.d
import std.string;
import std.zip;
import std.file;
import std.mbs;
import std.stdio;import std.windows.charset;
void main(char[][] args){
if (!isZip(args[1][])) {
//compress
ZipArchive comp = new ZipArchive();
ArchiveMember am1;
for (int i=1;i < args.length; i++) {
addArchiveMember(args[i][], comp, am1);
}
write(replaceExtension(args[1][]), comp.build());
}
else {
//extraction
char[] zipname = getFilename(args[1][]);
byte[] data = cast(byte[])read(args[1][]);
ZipArchive archive = new ZipArchive(data);
mkdir(getcwd() ~ '/' ~ getZipname(zipname));
chdir(getZipname(zipname));
foreach (ArchiveMember am; archive.directory) {
char name[] = mbs2utf(am.name.ptr);
mkdirs(name);
if(name[name.length-1]!='/'){
mkdirs(name);
ubyte[] out1 = archive.expand(am);
//write(getcwd() ~ '/' ~ toString(std.file.toMBSz(name)), out1);
write(getcwd() ~ '\\' ~ "aaa.zip", out1);//write(name, out1);
}
}
chdir("..");
}
}void addArchiveMember(char[] member,ZipArchive zip, ArchiveMember am) {
if (isdir(member)) {
getFilename(member);
member ~= '/';
char[][] flist = listdir(member);
for (int i=0; i < flist.length;i++) {
addArchiveMember(member ~ flist[i][], zip, am);
}
}
else {
am = new ArchiveMember();
am.name = toString(std.file.toMBSz(getFilename(member)));
am.expandedData = cast(ubyte[])read(member);
am.compressionMethod = 8;
zip.addMember(am);
}
}
char[] replaceExtension(char[] filename) {int dot = rfind(filename, '.');
if (dot == -1) {
return filename ~ ".zip";
}
else {
filename.length = dot;
return filename ~ ".zip";
}
}char[] getFilename(char[] argument) {
int hasdir = rfind(argument, "\\");
if (hasdir == -1) {
return argument;
}
else {
char[] filename = argument[hasdir+1 .. argument.length];
return filename;
}
}bool isZip(char[] filename) {
int dot = rfind(filename, '.');
if (dot == -1) {
return false;
}
else {
char[] extension = filename[dot+1 .. filename.length];
if (extension == "zip")
return true;
else
return false;
}
}void mkdirs(char[] dir) {
char[][] s = split(dir,"/");
char[] dirs="";
for (int i=0;iif(s[i] != ""){
dirs = dirs ~ s[i] ~ "/";
try{mkdir(dirs);}catch(Exception e){}
}
}
}char[] getZipname(char[] filename) {
int dot = rfind(filename, '.');
char[] name = filename[0 .. dot];
return name;
}
チラっとこの前言ったように、圧縮機能は完成!!
ファイル名にかかわらず、zip形式での圧縮が可能となりました!!!
これはうれしいですねー。このままver1.00としてリリースしたいくらいです。
でも展開ができないんですよねー。
デバッグのために意味わからないコードが書いてありますけど気にしないでね。
原因はなんだろう… ディレクトリの展開はうまくいってるみたい?なので
展開するファイルのパス?とかがおかしいのかも… 円マークとスラッシュの使い分けが出来てないんでしょうか…
まあここまで来たらあと一息さ!!
D言語
2007/02/09 17:12:21 comment(0) trackback(0)
コメントを書く
- トラックバックURL