PHPテキストファイルの改行コード検出

テキストファイルの改行コードの検出方法を考えてみました。
単純にファイルの先頭を数MB 読んで改行コードを判定する方法です。
改行コードが混在してたり、バイナリファイルだと正しく検出できません。

echo detectEOL("/tmp/test.txt");

function detectEOL($file) {
    if (!file_exists($file)) {
        return null;
    }

    $fpsrc = fopen($file, "r");
    if (!$fpsrc) {
        return null;
    }

    $chunk = fread($fpsrc, 10*1024);
    fclose($fpsrc);

    if (empty($chunk)) {
        return null;
    }

    if (substr_count($chunk, "\r\n")) {
        return '\r\n';
    }

    if (substr_count($chunk, "\r")) {
        return '\r';
    }

    return '\n';
}

PHPファイルエンコード変換

ファイルのエンコードを UTF-8 > Shift-JIS へ変換して、別ファイルへ出力するサンプルです。

ファイルの内容をすべて読み込んでエンコード変換する方法:

$srcfile = "/tmp/test.csv";
// 一時ファイルディレクトリにファイルを作成します
$dstfile = tempnam(sys_get_temp_dir(), 'prefix');

$contents = file_get_contents($srcfile);
$contents = mb_convert_encoding($contents, "Shift-JIS", "UTF-8");

$fp = fopen($dstfile , "w");

if ($fp) {
    fwrite($fp, $contents);
    fclose($fp);
}

上記方法だとファイルの内容が多いとメモリの使用上限に達することがあったので
少し改良した版:

$srcfile = "/tmp/test.csv";
// 一時ファイルディレクトリにファイルを作成します
$dstfile = tempnam(sys_get_temp_dir(), 'prefix');

$fpsrc = fopen($srcfile , "r");
$fpdst = fopen($dstfile , "w");

if ($fpsrc && $fpdst) {
    while(($chunk = fgets($fpsrc)) !== false) {
        $chunk = mb_convert_encoding($chunk, "Shift-JIS", "UTF-8");
        fwrite($fpdst, $chunk);
    }
}
if ($fpsrc) {
    fclose($fpsrc);
}
if ($fpdst) {
    fclose($fpdst);
}

マイナンバーのチェックデジットをVBAで算出

個人用マイナンバーのチェックデジットをVBAで算出してみました。

参考までに。。。

' http://law.e-gov.go.jp/announce/H26F11001000085.html
'
' (検査用数字を算出する算式)
' 第五条 令第八条の総務省令で定める算式は、次に掲げる算式とする。
' 算式
'  11―(n=1(シグマ)11(Pn×Qn))を11で除した余り)
'  ただし、(n=1(シグマ)11(Pn×Qn))を11で除した余り≦1の場合は、0とする。
' 算式の符号
'   Pn 個人番号を構成する検査用数字以外の十一桁の番号の最下位の桁を1桁目としたときのn桁目の数字
'  Qn 1≦n≦6のとき n+1 7≦n≦11のとき n―5
'
Function CalcCheckDigit(number As String) As Integer
    Dim digits As String
    Dim chkDigit As String
    Dim cd As Integer
    
    cd = -1

    ' 12桁でなければ無効
    If Len(number) <> 12 Then
        CalcCheckDigit = cd
        Exit Function
    End If
    
    ' チェックデジット部分を取出し
    chkDigit = Right(number, 1)
    
    ' マイナンバー11桁取出し
    digits = Left(number, 11)
    
    Dim n, pn, qn, m As Long
    Dim sum As Long
    
    res = False
    sum = 0
    
    For n = 1 To 11
        ' n桁目の数字
        ' 小さい桁から計算(検査用数字以外の十一桁の番号の最下位の桁を1桁目)
        pn = CInt(Mid(digits, 11 - n + 1, 1))
        
        ' 1≦n≦6のときn+1
        If n <= 6 Then
            qn = n + 1
        ' 7≦n≦11のときn―5
        Else
            qn = n - 5
        End If
        
        sum = sum + pn * qn
    Next
    
    ' 11 で割った余り
    m = sum Mod 11

    ' (n=1(シグマ)11(Pn×Qn))を11で除した余り≦1の場合は、0とする
    If m <= 1 Then
        cd = 0
    ' 11―(n=1(シグマ)11(Pn×Qn))を11で除した余り)
    Else
        cd = 11 - m
    End If

    CalcCheckDigit = cd
End Function

ためしに自分のマイナンバーで計算してみると合っていました。^_^;

参考サイト:
http://qiita.com/qube81/items/fa6ef94d3c8615b0ce64

URLからXMLファイルの読み込み

XMLデータを指定したURLから読み込むには、

$xml = simplexml_load_file($url);

または、

$xml = simplexml_load_string(file_get_contents($url));

で行えます。しかし、サーバーの設定によって指定した URL がリダイレクトされている場合には、リダイレクト先のURLから読み込みを行ってくれないようです。

例えば、curl_getinfo 関数で、当サイトのブログの RSS フィードを取得してみます。

結果は:

    [url] => http://www.northwind.mydns.jp/samples/blog/feed/
    [content_type] => text/html
    [http_code] => 301
    [header_size] => 348
    [request_size] => 71
    [filetime] => -1
    [ssl_verify_result] => 0
    [redirect_count] => 0
    [total_time] => 1.21189
    [namelookup_time] => 0.003149
    [connect_time] => 0.003198
    [pretransfer_time] => 0.0032
    [size_upload] => 0
    [size_download] => 0
    [speed_download] => 0
    [speed_upload] => 0
    [download_content_length] => 0
    [upload_content_length] => 0
    [starttransfer_time] => 1.211865
    [redirect_time] => 0
    [certinfo] => Array
        (
        )

    [redirect_url] => http://www.northwind.mydns.jp/samples/blog/feed/

http_code が 301 で、redirect_url にリダイレクト先の URL が返されました。

つまり、

$xml = simplexml_load_file("http://www.northwind.mydns.jp/samples/blog/feed/");

では期待していたフィードが得られないというわけです。

リダイレクト先の URL を指定すれば良いのですが、指定した URL がリダイレクトされているか不明の場合もあるので、getXmlFromUrl 関数を作ってみました。

function getXmlFromUrl($url, $defTimeout = 5) {
    $resultSet = false;
    $timeout = $defTimeout; // 0 をセットするとタイムアウトしない

    try {
        $ch = curl_init();

        curl_setopt ($ch, CURLOPT_URL, $url);
        curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);

        $res = curl_exec($ch);
        $info = curl_getinfo($ch);

        curl_close($ch);    

        if ($res && $info['http_code'] == 200) {
            $resultSet = simplexml_load_string($res);
        } else if ($info['http_code'] == 301) { // リダイレクト!
            $resultSet = getXmlFromUrl($info['redirect_url'], $defTimeout);
        } else {
            $resultSet = false;
        }
    } catch (Exception $e) {
    }

    return $resultSet;
}

Excel VBA でランダム文字列を生成

手っ取り早いランダム文字列を生成するExcel マクロを作成しました。

文字列の長さは8文字。生成した文字列をアクティブセルに表示します。

Sub RandomStr()
    On Error GoTo ErrHandler
   
    Const maxChars = 8
    
    Dim str As String
    Dim i As Integer
    Dim c As Integer
    Dim res As String
    
    str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    res = ""
    Randomize

    For c = 1 To maxChars
        ' Int((upperbound - lowerbound + 1) * Rnd + lowerbound)
        i = Int((Len(str) - 1 + 1) * Rnd + 1)
        res = res & Mid(str, i, 1)
    Next
    
    Debug.Print res
    ActiveCell.Value = res
    
    Exit Sub
ErrHandler:
    Debug.Print Err.Number & ":" & Err.Description
    Resume Next
End Sub