2011年12月16日金曜日

UTF-8のBOMを削除する

AccessでUTF-8のファイルをインポートしようとしたとき、
ビューで先頭に「・ソ」と表示された謎の文字がついていて、正しくインポートできなかった。
どうもこれはBOMらしい。
バイナリエディタで削除はできるけど、自動で削除する方法を2つほど見つけたのでメモ。

コードを書く前に参照設定で「Microsoft ActiveX Data Objects ~」を有効にすること。
BOMは先頭3バイトに着いてくる。
ならば4バイト目から先を出力しなおせばいいんだという手法。
ただし、ファイルが大きすぎるとメモリに入りきらないためエラー落ちする。
280MBまではちゃんと動いた、660MBではだめでした。

==================================================================
Dim readStream As ADODB.Stream
Dim writeStream As ADODB.Stream
Dim readFile As String
Dim writeFile As String

readFile = "C:\BOM付きファイル.txt"
writeFile = "C:\BOM無しファイル.txt"

' 4バイト目から読み込む
Set readStream = CreateObject("ADODB.Stream")
readStream.Open
readStream.Type = adTypeBinary
readStream.LoadFromFile (readFile)
readStream.Position = 3

' 出力ファイルをオープン
Set writeStream = CreateObject("ADODB.Stream")
writeStream.Open
writeStream.Type = adTypeBinary
' 読み込んだデータをそのままファイルに出力する(4バイト目以降を出力)
writeStream.Write (readStream.Read(adReadAll))
writeStream.SaveToFile writeFile, adSaveCreateOverWrite

' ファイルをクローズ
writeStream.Close
Set writeStream = Nothing
readStream.Close
Set readStream = Nothing
==================================================================

これはよくわからないが、たしかに削除できる。
ただし、Unicodeで保存されてしまう。
そのうち理解できたら役に立つかも。
 
cmd /u /c type BOMありUnicodeファイル > BOMなしUnicodeファイル 

2011年12月14日水曜日

バッチ作成時によく使うもの

■ファイル名にくっつける日時の取得
DBバックアップなどをバッチで自動化する場合、必ず実行ログを出力する。
そんなとき、大概ファイル名の後ろに日時をつけろって言われる。
簡単にできるけど毎回忘れて毎回調べてるので、覚えてる間にメモっておく。

echo %DATE:~0,4%%DATE:~5,2%%DATE:~8,2%
echo %TIME:~0,2%%TIME:~3,2%%TIME:~6,2%%TIME:~9,2%
 実行結果:
20111214
23150102

現在日時は 2011/12/14 23:15:01.02 でした。

■テンプレート
バッチを一から作るときのテンプレート。
setlocal、endlocal をよく忘れてしまうのでメモ。

@echo off
rem =================================================
rem 機能の説明
rem =================================================
setlocal

endlocal

■コマンド一覧
これがあればバッチ作成には困らないというサイトのリンク。
コマンドプロンプトを使ってみよう!
DOSコマンド一覧

子画面から親画面に値をセットする(JavaScript)

コードマスタなどの値をポップアップ画面で検索してセットということを
今まで携わったWebシステムではよくやっていた。
JavaScriptだけでサンプルが作れたのでメモ。
window.open で子画面を開き、window.opener で親画面にセットする流れ。
ついでに close して子画面も閉じる。

======================================================================

parent.html(親画面)
<html>
<head>
<title></title>
<script type="text/javascript">
    function windowOpen(controlName) {
        window.open("child.html?controlid=" + controlName,"new");
    }
</script>
</head>
<body>
子画面から選択した値を入れる
<input type="button" value="open" onclick="windowOpen('txtParent');">
<input type="text" id="txtParent">
</body>
</html>

======================================================================

======================================================================

child.html(子画面)
<html>
<head>
<title></title>
<script type="text/JavaScript">
    function setParentValue(){
        var controlId = getQuerystring("controlid");
        window.opener.document.getElementById(controlId).value = document.getElementById("txtValue").value;
        self.close();
    }
   
    function getQuerystring(key) { 
        var keyName = key.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
        var regex = new RegExp("[\\?&]" + keyName + "=([^&#]*)");
          
        var qs = regex.exec(window.location.href);
        if(qs == null) {
            return ""; 
        } else {
            return qs[1];
        }
    }
</script>
</head>
<body>
<input type="text" id="txtValue">
<input type="button" value="親画面に反映" onclick="setParentValue();">
</body>
</html>
======================================================================

Getで親画面のセット先のコントロールIDを渡すようにしているけど、
PHPとか.Net使うならセッションで管理するのがいいと思う。
上の例だとクエリストリングの取得サンプルも書けた。

JavaScriptでのクエリストリングの取り方

2011年12月13日火曜日

SVNコミット時にいろいろする方法

前にやってたSVNコミット時にメールを飛ばす方法を書いてる人がいたのでメモ。

Windows上のSubversionでコミット時にメールを送信する方法

さらに、コミット後に自動でチェックアウトする方法があるらしい。
SVNはリソース管理のみで、そんなことできるとは思わなかった。

SubversionにコミットしたらWEBサーバの内容も更新する方法
複数Webサイトの動作環境、しかもSVNコミット後即動作確認

コミット時にスクリプトを実行させ、自動でアップデートを掛けるらしい。
Javaなどコンパイルが必要なものはさらに仕掛けを作りこめばいけるんだろうか・・・
少なくともPHPやPerlなどは、コミット即動作確認は難しくなさそう。
ただし、コミットする度に上書きされてしまうため、前のバージョンの動作確認をするために
前のバージョンのソースをコミットするといったことが起きそう。
最新バージョンが最新じゃないって混乱しそうだ。

2011年12月9日金曜日

再帰クエリについて(PostgreSQL)

ちょっと再帰クエリについて調べてみたのでメモ。
自身のテーブルを再帰的に参照していくというもの。

========================================================================
WITH RECURSIVE tree_rec(id, parent, name, path, names) as(
    SELECT id, parent, name, array[id] as path,array[name] as names
    FROM tree
    WHERE parent IS NULL
    UNION ALL
    SELECT tree.ID, tree.parent, tree.name
               , tree_rec.path || tree.ID as path
               , tree_rec.names || tree.name as names
    FROM tree
    INNER JOIN tree_rec
    ON tree_rec.id = tree.parent
)

SELECT id, parent, name, path, names
          , array_upper(path, 1) AS level
          , array_to_string(names,'_')
FROM tree_rec
ORDER BY id;

========================================================================

結果、こんな感じ。
左3列がtreeテーブル本来のデータ。