テキストファイルを分割

テキストファイルを任意の行数ごとに分割し、別ファイルに保存します。

import javax.swing.*;
import java.io.*;
import javax.swing.filechooser.*;

public class TextDevider {

	/**
	 * 1ファイルあたりの行数
	 */
	private final static int MAX_LINE = 100;

	/**
	 * 分割するファイル
	 */
	private File target = null;

	public static void main(String[] args) {
		JFileChooser chooser = new JFileChooser();
		chooser.setFileFilter(new FileFilter() {
			public boolean accept(File file) {
				return file.getName().endsWith(".txt");
			}

			public String getDescription() {
				return "テキストファイル";
			}
		});

		if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
			TextDevider devider = new TextDevider(chooser.getSelectedFile());

			try {
				int num = devider.execDevide();
				System.out.println(num + "ファイルに分割");
			} catch (IOException e) {
				e.printStackTrace();
			}
		} else {
			System.out.println("キャンセル");
		}
	}

	/**
	 * TextDeviderクラスのコンストラクタです。分割するテキストファイルを引数として渡します。
	 * 
	 * @param file 分割するテキストファイル
	 */
	public TextDevider(final File file) {
		this.target = file;
	}

	/**
	 * テキストファイルの分割を実行します。分割したファイルは分割するファイルと同じディレクトリに保存されます。
	 * 
	 * @throws IOException
	 * @return 分割したファイル数
	 */
	public int execDevide() throws IOException {
		BufferedReader reader = null;
		PrintWriter writer = null;
		boolean isFinished = false;
		int fileCount = 0;

		try {
			reader = new BufferedReader(new FileReader(this.target));
			fileCount = 0;
			
			while (!isFinished) {
				File saveFile = new File(getSaveFilePath(fileCount));
				writer = new PrintWriter(new FileWriter(saveFile));
				String line = null;
				fileCount++;

				for (int lineCount = 0; lineCount < MAX_LINE
						&& (line = reader.readLine()) != null; lineCount++) {
					writer.println(line);
				}

				isFinished = (line == null);
				writer.close();
				writer = null;
			}
		} finally {
			if (writer != null) {
				writer.close();
			}
			// writer.closeは例外を投げないので、reader.closeは確実に実行される
			if (reader != null) {
				reader.close();
			}
		}
		return fileCount;
	}

	/**
	 * 分割したファイルのパスを決定します。
	 * 
	 * @param count
	 *            分割したファイルの順番を表す整数値
	 * @return 分割したファイルのパス
	 */
	private String getSaveFilePath(final int count) {
		return this.target.getPath() + "_" + count;
	}
}

簡単なオウム返し

JSPのうわさを聞いてちょっと試してみたのですが、思っていたよりも簡単でした。ウェブアプリを作るだけならば、RoRよりもJSPの方が手軽だったかもしれません。ただ新しい言語・フレームワークを学びたいので、RoRによる作成は続けようと思います。とりあえずの難関はMVCモデル!

<%@ page contentType="text/html; charset=Windows-31J" %>
<% request.setCharacterEncoding("Shift_JIS"); %>

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" />
    <title>JSP sample</title>
  </head>
  <body>
    <% if (request.getParameter("name") == null || (request.getParameter("name") == "")) { %>
      <p>はじめまして、あなたのお名前を教えてください。</p>
      <form method="post" action="test.jsp">
        <label for="name">あなたのお名前</label>
        <input type="text" name="name">
        <input type="submit" value="実行">
      </form>
    <% } else { %>
      <p>こんにちは、<%= request.getParameter("name") %>さん。</p>
    <% } %>
  </body>
</html>

HSVを指定して色を取得する

HSVDelphiPascal)でHSV形式を利用するための自作関数。

unit HSVtoColor2;

interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    procedure FormCreate(Sender: TObject);
  private
    function getTColor(const h:Integer; const s, v:Double):TColor;
  end;

var
  Form1: TForm1;

implementation
{$R *.dfm}

uses
  Math;


procedure TForm1.FormCreate(Sender: TObject);
var
  x:integer;
begin
  with Image1.Canvas do
  begin
    Pen.Width := 1;
    for x := 0 to Image1.Width - 1 do
    begin
      Pen.Color := getTColor(Round(360*x/Image1.Width), 1.0, 1.0);
      MoveTo(x, 0);
      LineTo(x, Image1.Height);
    end;
  end;
end;

// HSVを指定してTColorを得る関数
// 変換式はWikipediaより引用
function TForm1.getTColor(const h:Integer; const s, v:Double):TColor;
  // GRBを指定してTColorを得る関数
  function RGBtoTColor(const r,g,b:Double):TColor;
  begin
    result := Round($FF * Min(1.0, Max(0.0, r))) OR
      (Round($FF * Min(1.0, Max(0.0, g))) shl 8) OR
      (Round($FF * Min(1.0, Max(0.0, b))) shl 16);
  end;
var
  _h, hi :integer;
  _s, _v, f, p, q, t :Double;
begin
  // 0<=h<3600.0<=s<=1.00.0<=v<=1.0に収める
  _h := h mod 360;
  _s := Min(1.0, Max(0.0, s));
  _v := Min(1.0, Max(0.0, v));
  while _h < 0 do _h := _h + 360;

  if _s = 0.0 then
  begin
    result := RGBtoTColor(_v, _v, _v);
  end
  else begin
    hi := Floor(_h/60) mod 6;
    f := _h/60 - hi;
    p := _v * (1.0 - _s);
    q := _v * (1.0 - f * _s);
    t := _v * (1.0 - (1.0 - f) * _s);

    case hi of
      0: result := RGBtoTColor(_v,t,p);
      1: result := RGBtoTColor(q,_v,p);
      2: result := RGBtoTColor(p,_v,t);
      3: result := RGBtoTColor(p,q,_v);
      4: result := RGBtoTColor(t,p,_v);
      else result := RGBtoTColor(_v,p,q);
    end;
  end;
end;

end.

RPGっぽく戦闘してみる

テキストRPGのように自動戦闘を行います。ヘタレ英語なのは仕様です。

Dragon's attack!
Mini slime gets 23 damage!
Mini slime's attack!
Dragon gets 2 damage!

Dragon's attack!
Mini slime gets 23 damage!

Mini slime's HP is zero!
Dragon won!

# モンスターを表すクラス
class Monster
  attr_reader :name, :attack, :guard, :speed
  
  def initialize(name,hp,attack,guard,speed)
    @name = name
    @hp = hp
    @attack = attack
    @guard = guard
    @speed = speed
  end

  # ダメージ判定
  def damage_from(attacker)
    # 与えるダメージを算出
    damage = attacker.attack - @guard

    if damage > 0 then
      @hp -=  damage
      puts  "#{@name} gets #{damage} damage!"
    else
      puts "#{@name} gets no damage!"
    end
  end

  # 攻撃
  def attack_to(target)
    puts "#{self.name}'s attack!"
    avoid_percent = target.speed - self.speed
    if rand(100) >= avoid_percent  then
      target.damage_from(self)
    else
      puts "But #{target.name} avoids!"
    end
  end

  # 敗北判定
  def is_lose
    return @hp <= 0
  end
end

class Boss < Monster
  # ボスは必中
  def attack_to(target)
    puts "#{self.name}'s attack!"
    target.damage_from(self)
  end
end


# 戦闘処理
def battle(m1,m2)
  # ターン経過
  def do_turn(fast_attacker,slow_attacker)
    fast_attacker.attack_to(slow_attacker)
    slow_attacker.attack_to(fast_attacker) unless slow_attacker.is_lose
    puts ''
  end
  
  # 勝者判定
  def judge(m1,m2)
    if m1.is_lose then
      winner = m2
      loser = m1
    else
      winner = m1
      loser = m2
    end
    puts "#{loser.name}'s HP is zero!"
    puts "#{winner.name} won!"  
  end
  
  # 戦闘処理開始
  # 先攻後攻判定(speed不変前提)
  if m1.speed < m2.speed then
    # m2 がm1よりも早い
    fast_attacker = m2
    slow_attacker = m1
  else
    fast_attacker = m1
    slow_attacker = m2      
  end

  # 勝敗が決まるまで戦闘
  until (m1.is_lose or m2.is_lose) do
    do_turn(fast_attacker,slow_attacker)
  end
  judge(m1,m2)
end

def main
  mob = Monster.new('Mini slime',40,10,2,2)
  boss = Boss.new('Dragon',200,25,8,5)
  battle(mob, boss)
end

main

砂時計ツール

俗に言うキッチンタイマー。個人的に使うもので、エラー処理はほとんど行っていない。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace MyClock
{
    public partial class Form1 : Form
    {
        const string btn_clock_start = "測定開始";
        const string btn_clock_stop = "停止";
        DateTime start_Time;    // 計測を開始した時間
        int limit_Time;         // 計測する時間の長さ(分)

        public Form1()
        {
            InitializeComponent();
            button1.Text = btn_clock_start;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (button1.Text == btn_clock_start)
            {
                clock_Start();
            }
            else
            {
                timer1.Enabled = false;
                clock_Stop();
            }
        }

        // 計測開始
        private void clock_Start()
        {
            limit_Time = int.Parse(comboBox1.Text);
            if (limit_Time <= 0) {
                return;
            }
            button1.Text = btn_clock_stop;
            timer1.Enabled = true;
            start_Time = DateTime.Now;
        }

        // 計測終了
        private void clock_Stop()
        {
            button1.Text = btn_clock_start;
            timer1.Enabled = false;
            progressBar1.Value = 0;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            TimeSpan ts = DateTime.Now.Subtract(start_Time);
            int value = (int)(100 * ts.TotalMinutes / limit_Time);
            progressBar1.Value = value;
            if (ts.Minutes >= limit_Time)
            {
                clock_Stop();
                MessageBox.Show("終了しました。");
            }
        }
    }
}

リストをHTMLに変換

(define (list-to-item l)
  (if (not (null? l))
      (begin
        (display "  <li>")
        (display (car l))
        (display "</li>")
        (newline)
        (list-to-item (cdr l)))))
(define (list-to-ul l)
  (begin 
    (display "<ul>")
    (newline)
    (list-to-item l)
    (display "</ul>")
    (newline)))
(define (list-to-ol l)
  (begin 
    (display "<ol>")
    (newline)
    (list-to-item l)
    (display "</ol>")
    (newline)))

(list-to-ul '("アイテムA" "アイテムB" "アイテムC"))
; => <ul>
;      <li>アイテムA</li>
;      <li>アイテムB</li>
;      <li>アイテムC</li>
;    </ul>

(list-to-ol '("アイテム1" "アイテム2" "アイテム3"))
; => <ol>
;      <li>アイテム1</li>
;      <li>アイテム2</li>
;      <li>アイテム3</li>
;    </ol>

; 以下の形式は未対応
; (list-to-ul '("アイテムA" '("アイテムB1" "アイテムB2") "アイテムC"))

HTML内の見出し一覧を取得する

import java.io.*;
import java.util.*;
import java.util.regex.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;

public class HTMLIndexMaker {
 public static void main(String[] args) {
  // ファイルを選択する
  File file = selectFile(null);
  if (file == null || file.isDirectory() || !file.canRead()) {
   // ファイルが選択されなかった・読み込めなかった
   System.exit(0);
  }

  // 選択したファイルを読み込む
  String html = getHTML(file);
  // 正規表現を用い、見出し要素を取り出す
  List<String> list = getList(html);
  // 取り出した要素を表示
  showList(list);
  // 実行終了
  System.out.println("finish..." + list.size() + "個の見出しを検出しました");
 }

 /**
  * ダイアログを開きファイルを選択する
  * 参照->http://www.javadrive.jp/tutorial/jfilechooser/index.html
  * @return 選択したファイル(非選択時はnull)
  */
 private static File selectFile(final JFrame frame) {
  JFileChooser fileChooser = new JFileChooser();
  fileChooser.setMultiSelectionEnabled(false);
  FileNameExtensionFilter filter = new FileNameExtensionFilter("HTMLファイル", "html", "htm");
  fileChooser.addChoosableFileFilter(filter);

  if (fileChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
   return fileChooser.getSelectedFile();
  } else {
   return null;
  }
 }

 /**
  * HTMLファイルの内容(テキスト)をStringに読み込む
  * HTMLファイルはシフトJIS(MS932)であること
  * 参考->http://www.ne.jp/asahi/hishidama/home/tech/java/file.html
  */
 private static String getHTML(final File file) {
  StringBuffer sb = new StringBuffer();
  InputStream is = null;
  Reader r = null;
  BufferedReader br = null;
  try {
   is = new FileInputStream(file);
   r = new InputStreamReader(is, "MS932");
   br = new BufferedReader(r);
   while (br.ready()) {
    sb.append(br.readLine());
   }
  } catch (Exception e) {
   throw new RuntimeException(e);
  } finally {
   if (br != null) {
    try {
     br.close();
    } catch (IOException e) {
    }
   }
   if (r != null) {
    try {
     r.close();
    } catch (IOException e) {
    }
   }
   if (is != null) {
    try {
     is.close();
    } catch (IOException e) {
    }
   }
  }
  return sb.toString();
 }

 /**
  * Stringを検索し、見出し一覧を作成する
  * 
  * @param html 検索するHTML
  * @return 見出し一覧
  */
 private static List<String> getList(final String html) {
  List<String> list = new ArrayList<String>();
  Pattern pattern = Pattern.compile("<h[1-6].+?</h[1-6]>");
  Matcher matcher = pattern.matcher(html);
  while (matcher.find()) {
   list.add(matcher.group());
  }
  return list;
 }

 /**
  * リストを表示する(デバッグ用)
  * 
  * @param list 見出し一覧
  */
 private static void showList(final List<String> list) {
  ListIterator li = list.listIterator();
  while (li.hasNext()) {
   System.out.println(li.next().toString());
  }
 }
}