Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
はてなダイアリー - taediumの日記
[go: Go Back, main page]

Hatena::Diary
   
はてな
 ようこそゲストさん  最新の日記 ユーザー登録 ログイン ヘルプ

taediumの日記

Java | Groovy | J2EE | Seasar | Spring | Struts | RUP | OO設計 | | misc |

2004 | 02 | 03 | 04 | 05 | 06 | 07 | 08 |
<前の日 | 次の日>

2004-05-04

[][] I/Oまわり練習

Groovyでとにかくなんか作ってみよう、ということで題材探し。

しばらく前の日経ソフトウェアスクリプト言語の特集があったことを思い出した。2003年9月号のPerlRubyの特集。「スクリプト言語の便利さを実感する五つの例題」という記事があった。ファイルを読み書きしているし丁度よさそう。でも解答は当然PerlRubyのコード。PerlRubyもまったく読めないけど解説を頼りに挑戦してみよ。


  • 例題1 メールアドレスをマージしてソート

1000行のメールアドレスを収めたファイルを読み込み、メールアドレスの重複を省いて並べ替える。

import java.io.*
import java.util.*

file = new File(args[0])

file.withReader {reader |
    list = reader.readLines()     
    set = new TreeSet(list)
    
    set.each {
        println it
    }
}

  • 例題2 CSVのカラムを入れ替える

4カラムからなるCSVファイルの2番目と3番目を入れ替える

import java.io.*
import java.util.*

file = new File(args[0])

file.withReader {reader |
    list = reader.readLines()     
    
    list.each {
        cols = it.tokenize(",")
        Collections.swap(cols, 1, 2)
        println cols.join(",")
    }
}

  • 例題3 複数ファイルのサイズと最初の3文字を一覧

異なるデータが入っている1000個のテキストファイルのサイズと最初の3文字を一覧にする。テキストファイルはあるディレクトリかそのサブディレクトリに入っている。

import java.io.*

dir = new File(args[0])
tree dir

def tree(dir) {
    num = 3
    
    if (dir.isFile()) {
        
        dir.withReader { reader |
            // charの配列が使えないので1行読み取り
            line = reader.readLine()
            if (line.size() >= num) { 
                chars = line.substring(0,num)
            } else {
                chars = line
            }
            
            println "name=${dir.name} size=${dir.length()} chars=${chars}"
        }
        // なにかを明示的に返さないとおこられるのでnullを返す
        return null 
    } 
    
    array = dir.listFiles()
    
    if (array == null) {
        return null
    } 
    
    // array.each {...}の中で再帰呼び出しをしようと
    // したけどおこられたのでforをつかう
    for (file in array) {
        tree file
    } 
}

  • 例題4 例題2と例題3の結果をExcel形式で保存

(記事にはExcelとはOLEで連結するとあるけれど、OLEってよくわからない。POIでできそうだしとりあえず気にしないことにしよう。)

import org.apache.poi.hssf.usermodel.*
import java.io.*

book = new HSSFWorkbook()

files = []
args.each {
    files << new File(it)
}

files.each { file |
    sheetName = file.name.tokenize("\\.").getAt(-2)
    sheet = book.createSheet(sheetName)
    rowIdx = 0
    
    file.eachLine { line |
        row = sheet.createRow(rowIdx++)
        cellIdx = 0
        line.tokenize(",").each { 
            cell = row.createCell((Short)cellIdx++)
            cell.setCellValue(it)
        }
    }
}

// 変数streamのクラスはjava.io.BufferedOutputStream
new File("test.xls").withOutputStream { stream |
    book.write(stream)
}

  • 例題5 HTMLの構文をチェックする

(時間切れ。また今度挑戦する、眠いよ...)


気づいたことなど

  • 配列の要素数取得にarray.lengthとできない。array.size()とする。
  • Javaのようにreturnだけの記述じゃだめなのか?(明示的に何かを返さなければいけない?)
  • eachのようなクロージャを使ったループ内からはクラスに属さないメソッドを呼べない?(普通のメソッドに対しての呼び出しは試してない)
  • 上記のコードはgroovy-1.0-beta-4で作った。違うバージョンではまた違った書き方が可能になるかもということに注意。とくにプリミティブ型の配列。

[] TelnetみたいなHttpクライアント

id:masanobuimaiさんの日記より

http://d.hatena.ne.jp/masanobuimai/20040115#p3

面白そう。あとで見よう。

[] org.codehaus.groovy.syntax.SyntaxException

思い切りはまった。Groovyスクリプトファイルを実行すると次のようなメッセージが表示された。

C:\work\groovy\example>groovy test.groovy
[]
[]
Caught: org.codehaus.groovy.syntax.SyntaxException: Cannot use a class expressio
n on the left hand side of an assignment. At [-1:-1] test.groovy

原因はgroovyスクリプトファイルと同名の変数に値を代入しようとしたから。

たとえば「test.groovy」というファイルを使う場合、次のようなコードで実行するとSyntaxExceptionとなる。

test = 'hoge'

testは暗黙的に定義されているClass型の変数扱いになり、この場合だと自分自身の「test」クラスを持っていることがわかった。すなわち次のコードが問題ないことになる。

assert test === this.class

次のようなこともわかった。クロージャを使ってみた場合...

list = [1,2,3]
list.each { test |
    println test
}

結果はこんな風になる。

class test
class test
class test

一方、forループを使ってみた場合は...

list = [1,2,3]
for (test in list) {
    println test
}

Exceptionが発生する。

ファイルと同名の変数を使わないようにしないといけないのか。でも絶対うっかり使ってしまうだろうな。

<前の日 | 次の日>

mailaddress