プログラマメモ2 - programmer no memo2

目次

手習い しゅうごうのえんざん 2008/02/28
2008/02/28

Groovyです。

集合の計算


def a = [1, 2, 4]
def b = [1, 2, 3, 4]
def c = [3, 4]
def d = [1, 4]

// a ∩ (b ∪ c ∪ d)
// b ∩ (c ∪ d)
// c ∩ d

a = a - (b + c + d)
b = b - (c + d)
c = c - d
println a
println b
println c
println d


結果
[]
[2]
[3]
[1, 4]

時計算 2008/02/26

長針は一時間に360°回転するから、一分間に6°回転
短針は一時間に30°回転するから、一分間に1/2°回転

360÷60=6

(360÷12)÷60=0.5

長針と短針の速さの差は、一分間で(6−0.5)

3時から4時までの間で針が重なる時刻は何時何分か。

[erlang]変化しない変数 - Erlangの変数は単一代入 2008/02/25

Erlanの変数は単一代入だそうです。変数に値を一度しか入れないものだそうです。
Javaだとfinalつけた変数に値を入れるようなものですね。

既に変数が代入されている変数は束縛済み変数(bound variable)、そうでないものは未束縛変数(unbound variable)というそうです。

で、
プログラミングErlang
Joe Armstrong 榊原一矢
4274067149

の変数の章にあるコラムに「単一代入は代数のようなもの」とありまして、数学の変数とErlangの変数が同じだよといっていて興味深いです。

ちなみに、出典が思い出せないのですが、プログラム言語の初心者に変数を《小さな箱》としておしえることの弊害を説いてたのがあったのですが...
僕自身も変数を《小さな箱》として、たとえて教えるのは何かまずいような気がするんですよね。
ビギナーに対して他のイメージにたとえて教えるってことよくあると思うんですが、怖いのは、たとえをたとえでなくそのものとして刷り込まれてしまう危険性があるということで。あなたが彼、彼女に教えたばかりに彼、彼女の才能を殺したかもしれない...なんてね。

数学の問題を好きなプログラミング言語で解く「Project Euler(オイラー)」 2008/02/25
2008/03/05

Project Euler
via.オレンジニュース(2008-02-22)

プロブレムの1番を試しにチャレンジ。

org.apache.commons.collections.CollectionUtils.unionを使ってます。

belowは、~未満

package m;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static org.apache.commons.collections.CollectionUtils.union;

public class P1 {

public static void main(String[] args) {
List<Integer> a = b(1000, 3);
List<Integer> b = b(1000, 5);
Collection<Integer> c = union(a, b);
System.out.println(c);
System.out.println(sum(c));
}

static int sum(Collection<Integer> collection) {
int sum = 0;
for (Integer integer : collection) {
sum += integer;
}
return sum;
}

static List<Integer> b(int m, int t) {
List<Integer> list = new ArrayList<Integer>();
int i = 0;
int a = 0;
while (true) {
a = (t * (++i));
if ((m - 1) < a)
break;
list.add(a);
}
return list;
}
}

[css]リンクの下線を消す。 2008/02/24

リンクの下線を消したい場合。

a {
text-decoration: none;
}


スタイルシート[CSS]/リンク/リンク文字の下線を消す - TAG index

[css]もうcssハックをやめたい。 2008/02/23

ひとつのcssでいろいろなブラウザに対応させるテクニックをCSSハックといったりするようですね。

もう疲れました。ひとつのcssでieに対応させる道を断念しようと思いました。
調べていくと、ieのためのcssの読み込みをおこなう方法がありました。

この方法を使うと、ie専用のcssを読み込ませることができます。

<!--[if IE ]>
<link href='http://deiji.jp/css/programmermemo3/ie.css' media='screen' rel='stylesheet' type='text/css'/>
<![endif]-->


もうこれでいくしかありません。
Orz...

参考

[css]ie6でのwidth,padding 2008/02/23

cssをいじっていてはじめからieを考慮にいれないとデザインできないことがわかったので、面倒だけど、こつこつこつこつやっています。

width = width -(paddingのeleft + paddingのright)
ですが、これを素直に実行するとieでひどいめにあいますね。

firefox,safariだとオッケーなのに...

自分なりの、ぎりぎりの妥協線としてdivにdivを入れ子にして、上のdivで、width,marginを設定して中のdivでpadding設定。

でも、これでもだめですが、トライアンドエラーを繰り返すのに疲れました。
orz...


外字への道 その3 2008/02/21
2008/03/19

このコードはだめです。20080319
新しいサンプルコードは、プログラマメモ2: 外字への道 その4

javassistを使ってます。
一字一字調べて外字であれば、フォントファミリをEUDCにしています。
うまくいっているように思えます。

static {

ClassPool pool = ClassPool.getDefault();

CtClass myCtClass;
try {
myCtClass = pool.get("net.sf.jasperreports.engine.export.TextRenderer");
CtMethod ctMethod = myCtClass.getDeclaredMethod("renderParagraph");

StringBuffer buffer = new StringBuffer();
buffer.append(" {");
buffer.append(" java.text.AttributedCharacterIterator paragraph = null;");
buffer.append(" ");
buffer.append(" if ($3 == null)");
buffer.append(" {");
buffer.append(" paragraph = ");
buffer.append(" new java.text.AttributedString(");
buffer.append(" \" \",");
buffer.append(" new java.text.AttributedString(");
buffer.append(" $1, ");
buffer.append(" $2, ");
buffer.append(" $2 + 1");
buffer.append(" ).getIterator().getAttributes()");
buffer.append(" ).getIterator();");
buffer.append(" }");
buffer.append(" else");
buffer.append(" {");
buffer.append(" paragraph = ");
buffer.append(" new java.text.AttributedString(");
buffer.append(" $1, ");
buffer.append(" $2, ");
buffer.append(" $2 + $3.length()");
buffer.append(" ).getIterator();");
buffer.append(" }");
buffer.append("");
buffer.append(" java.awt.font.LineBreakMeasurer lineMeasurer = new java.awt.font.LineBreakMeasurer(paragraph, net.sf.jasperreports.engine.export.TextRenderer.LINE_BREAK_FONT_RENDER_CONTEXT);");
buffer.append(" ");
buffer.append(" while (lineMeasurer.getPosition() < paragraph.getEndIndex() && !isMaxHeightReached)");
buffer.append(" {");
buffer.append(" ");
buffer.append(" int startIndex = lineMeasurer.getPosition();");
buffer.append(" ");
buffer.append("");
buffer.append(" java.awt.font.TextLayout layout = lineMeasurer.nextLayout(formatWidth);");
buffer.append("");
buffer.append(" if (isMinimizePrinterJobSize)");
buffer.append(" {");
buffer.append(" ");
buffer.append(" java.text.AttributedString tmpText = ");
buffer.append(" new java.text.AttributedString(");
buffer.append(" paragraph, ");
buffer.append(" startIndex, ");
buffer.append(" startIndex + layout.getCharacterCount()");
buffer.append(" );");
buffer.append(" char[] cs = $3==null?new char[0]:$3.toCharArray();");
buffer.append(" for(int i=0;i<cs.length;i++){");
buffer.append(" java.util.Map map = new java.util.LinkedHashMap();");
buffer.append(" ");
buffer.append(" if(0xe000 <= cs[i] && cs[i] <= 0xf8ff){");
buffer.append(" map.put(java.awt.font.TextAttribute.FAMILY, \"EUDC\");");
buffer.append(" tmpText.addAttributes(map, i, i+1);");
buffer.append(" continue;");
buffer.append(" }");
buffer.append(" ");
buffer.append(" tmpText.addAttributes(map, i, i+1);");
buffer.append(" }");
buffer.append(" ");
buffer.append(" layout = new java.awt.font.TextLayout(tmpText.getIterator(), grx.getFontRenderContext());");
buffer.append(" ");
buffer.append(" }");
buffer.append("");
buffer.append(" float lineHeight = lineSpacingFactor * ");
buffer.append(" maxFontSizeFinder.findMaxFontSize(");
buffer.append(" new java.text.AttributedString(");
buffer.append(" paragraph, ");
buffer.append(" startIndex, ");
buffer.append(" startIndex + layout.getCharacterCount()");
buffer.append(" ).getIterator(),");
buffer.append(" fontSize");
buffer.append(" );");
buffer.append("");
buffer.append(" if (drawPosY + lineHeight <= textHeight)");
buffer.append(" {");
buffer.append(" drawPosY += lineHeight;");
buffer.append(" ");
buffer.append(" switch (horizontalAlignment)");
buffer.append(" {");
buffer.append(" case 4 :");
buffer.append(" {");
buffer.append(" if (layout.isLeftToRight())");
buffer.append(" {");
buffer.append(" drawPosX = 0;");
buffer.append(" }");
buffer.append(" else");
buffer.append(" {");
buffer.append(" drawPosX = formatWidth - layout.getAdvance();");
buffer.append(" }");
buffer.append(" if (lineMeasurer.getPosition() < paragraph.getEndIndex())");
buffer.append(" {");
buffer.append(" layout = layout.getJustifiedLayout(formatWidth);");
buffer.append(" }");
buffer.append("");
buffer.append(" break;");
buffer.append(" }");
buffer.append(" case 3 :");
buffer.append(" {");
buffer.append(" drawPosX = formatWidth - layout.getAdvance();");
buffer.append(" break;");
buffer.append(" }");
buffer.append(" case 2 :");
buffer.append(" {");
buffer.append(" drawPosX = (formatWidth - layout.getAdvance()) / 2;");
buffer.append(" break;");
buffer.append(" }");
buffer.append(" case 1 :;");
buffer.append(" default :");
buffer.append(" {");
buffer.append(" drawPosX = 0;");
buffer.append(" }");
buffer.append(" }");
buffer.append("");
buffer.append(" draw(layout);");
buffer.append(" }");
buffer.append(" else");
buffer.append(" {");
buffer.append(" isMaxHeightReached = true;");
buffer.append(" }");
buffer.append(" }");
buffer.append(" }");

ctMethod.setBody(new String(buffer));

myCtClass.toClass();
} catch (NotFoundException e) {
e.printStackTrace();
} catch (CannotCompileException e) {
e.printStackTrace();
}

}

外字かどうかの判定は 2008/02/21



悩んでほうぼうに聞いたあげくはじめからwikipediaみたほうがはやかったかもという結論に...

Unicodeでは、外字エリアとして私用領域という名称でU+E000〜U+F8FF、U+000F0000〜U+000FFFFD、U+00100000〜U+0010FFFDに外字領域を設けてある。外字 - Wikipedia


windowsの場合、すごく乱暴だけど、0xe000~0xf8ffであるものは単純に外字でよいのかも。
だめかな...

そうするならば、下記のコードでいいんじゃんという気がするんだけど。
public static boolean isGaiji(char c) {

if(0xe000 <= c && c <= (0xf8f0 + 0xf)){
return true;
}

return false;
}

[java]TextAttribute FAMILYの使い方をまちがっていたOrz... 2008/02/21

あああ

java.awt.font.TextAttributeのFAMILYを理解しないままで使っていました...

まちがった情報で書いた記事
プログラマメモ2: jasperreports 外字への道 その2 アイデア実証レベル

javadocによりますと、

フォントファミリの名前です。ファミリ名が見つからない場合には、デフォルトフォントが使用されます。名前には、完全フォント名やほかの属性 ("Helvetica Bold" 名など) を指定しないでください。このような名前の場合、既知のファミリ名と一致しないために、デフォルトフォントが使用されることがあります。javadoc


うまくいっているようにみえたのまちがった値を入れて、デフォルトフォントになっていたからでした。

jasperreports 外字への道 その2 アイデア実証レベル 2008/02/21

この記事での、java.awt.font.TextAttribute.FAMILYの使い方まちがっていました!!!!!

JasperReportsです。
windowsのみでの話しです。

JasperReportsをつかってPDFを出力とかではなくて、JasperReportsを付属のviewerに表示するときとかの話です。

外字(EUDC)を表示するための実証コードです。

対象としているのは、JasperReports 2.0.4
使用しているjavassistのバージョンは、3.6.0.GA

どういうふうにやっているかといいますと、net.sf.jasperreports.engine.export.TextRendererのrenderParagraphメソッドで処理に手を加えることで、外字混在で表示させています。

メソッドの中身を下記のようにします。※変更箇所は色かえてます。

{
AttributedCharacterIterator paragraph = null;

if (lastParagraphText == null)
{
paragraph =
new AttributedString(
" ",
new AttributedString(
allParagraphs,
lastParagraphStart,
lastParagraphStart + 1
).getIterator().getAttributes()
).getIterator();
}
else
{
paragraph =
new AttributedString(
allParagraphs,
lastParagraphStart,
lastParagraphStart + lastParagraphText.length()
).getIterator();
}

LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, LINE_BREAK_FONT_RENDER_CONTEXT);//grx.getFontRenderContext()

while (lineMeasurer.getPosition() < paragraph.getEndIndex() && !isMaxHeightReached)
{
//eugene fix - start
int startIndex = lineMeasurer.getPosition();
//eugene fix - end

TextLayout layout = lineMeasurer.nextLayout(formatWidth);

if (isMinimizePrinterJobSize)
{
//eugene fix - start
AttributedString tmpText =
new AttributedString(
paragraph,
startIndex,
startIndex + layout.getCharacterCount()
);
java.util.Map map = new java.util.LinkedHashMap();
map.put(java.awt.font.TextAttribute.FAMILY, "MS ゴシック,EUDC");
tmpText.addAttributes(map, startIndex, startIndex + layout.getCharacterCount());

layout = new TextLayout(tmpText.getIterator(), grx.getFontRenderContext());
//eugene fix - end
}

float lineHeight = lineSpacingFactor *
maxFontSizeFinder.findMaxFontSize(
new AttributedString(
paragraph,
startIndex,
startIndex + layout.getCharacterCount()
).getIterator(),
fontSize
);

if (drawPosY + lineHeight <= textHeight)
{
drawPosY += lineHeight;

switch (horizontalAlignment)
{
case JRAlignment.HORIZONTAL_ALIGN_JUSTIFIED :
{
if (layout.isLeftToRight())
{
drawPosX = 0;
}
else
{
drawPosX = formatWidth - layout.getAdvance();
}
if (lineMeasurer.getPosition() < paragraph.getEndIndex())
{
layout = layout.getJustifiedLayout(formatWidth);
}

break;
}
case JRAlignment.HORIZONTAL_ALIGN_RIGHT :
{
drawPosX = formatWidth - layout.getAdvance();
break;
}
case JRAlignment.HORIZONTAL_ALIGN_CENTER :
{
drawPosX = (formatWidth - layout.getAdvance()) / 2;
break;
}
case JRAlignment.HORIZONTAL_ALIGN_LEFT :;
default :
{
drawPosX = 0;
}
}

draw(layout);
}
else
{
isMaxHeightReached = true;
}
}
}


つぎにこのコードをJasperReportsのソースを変更せずにロジックだけ変更します。
ここでJavassistを使います。Javassistを使うと、バイトコードを変更することができます。すごい便利です。

大本のライブラリを、コンパイルしなおす必要がない、もしくはしたくないときとかに重宝します。


下記のコードをJasperReportsを使用するクラスとかに貼ります。staticなブロックにしています。
static {
ClassPool pool = ClassPool.getDefault();

CtClass myCtClass;
try {
myCtClass = pool.get("ja.TextRenderer");
CtMethod ctMethod = myCtClass.getDeclaredMethod("renderParagraph");

ctMethod.getMethodInfo2().setAccessFlags(AccessFlag.PUBLIC);

StringBuffer buffer = new StringBuffer();
buffer.append(" {");
buffer.append(" java.text.AttributedCharacterIterator paragraph = null;");
buffer.append(" ");
buffer.append(" if ($3 == null)");
buffer.append(" {");
buffer.append(" paragraph = ");
buffer.append(" new java.text.AttributedString(");
buffer.append(" \" \",");
buffer.append(" new java.text.AttributedString(");
buffer.append(" $1, ");
buffer.append(" $2, ");
buffer.append(" $2 + 1");
buffer.append(" ).getIterator().getAttributes()");
buffer.append(" ).getIterator();");
buffer.append(" }");
buffer.append(" else");
buffer.append(" {");
buffer.append(" paragraph = ");
buffer.append(" new java.text.AttributedString(");
buffer.append(" $1, ");
buffer.append(" $2, ");
buffer.append(" $2 + $3.length()");
buffer.append(" ).getIterator();");
buffer.append(" }");
buffer.append("");
buffer.append(" java.awt.font.LineBreakMeasurer lineMeasurer = new java.awt.font.LineBreakMeasurer(paragraph, net.sf.jasperreports.engine.export.TextRenderer.LINE_BREAK_FONT_RENDER_CONTEXT);");
buffer.append(" ");
buffer.append(" while (lineMeasurer.getPosition() < paragraph.getEndIndex() && !isMaxHeightReached)");
buffer.append(" {");
buffer.append(" ");
buffer.append(" int startIndex = lineMeasurer.getPosition();");
buffer.append(" ");
buffer.append("");
buffer.append(" java.awt.font.TextLayout layout = lineMeasurer.nextLayout(formatWidth);");
buffer.append("");
buffer.append(" if (isMinimizePrinterJobSize)");
buffer.append(" {");
buffer.append(" ");
buffer.append(" java.text.AttributedString tmpText = ");
buffer.append(" new java.text.AttributedString(");
buffer.append(" paragraph, ");
buffer.append(" startIndex, ");
buffer.append(" startIndex + layout.getCharacterCount()");
buffer.append(" );");
buffer.append(" java.util.Map map = new java.util.LinkedHashMap();");
buffer.append(" map.put(java.awt.font.TextAttribute.FAMILY, \"MS ゴシック,EUDC\");");
buffer.append(" tmpText.addAttributes(map, startIndex, startIndex + layout.getCharacterCount());");
buffer.append(" layout = new java.awt.font.TextLayout(tmpText.getIterator(), grx.getFontRenderContext());");
buffer.append(" ");
buffer.append(" }");
buffer.append("");
buffer.append(" float lineHeight = lineSpacingFactor * ");
buffer.append(" maxFontSizeFinder.findMaxFontSize(");
buffer.append(" new java.text.AttributedString(");
buffer.append(" paragraph, ");
buffer.append(" startIndex, ");
buffer.append(" startIndex + layout.getCharacterCount()");
buffer.append(" ).getIterator(),");
buffer.append(" fontSize");
buffer.append(" );");
buffer.append("");
buffer.append(" if (drawPosY + lineHeight <= textHeight)");
buffer.append(" {");
buffer.append(" drawPosY += lineHeight;");
buffer.append(" ");
buffer.append(" switch (horizontalAlignment)");
buffer.append(" {");
buffer.append(" case 4 :");
buffer.append(" {");
buffer.append(" if (layout.isLeftToRight())");
buffer.append(" {");
buffer.append(" drawPosX = 0;");
buffer.append(" }");
buffer.append(" else");
buffer.append(" {");
buffer.append(" drawPosX = formatWidth - layout.getAdvance();");
buffer.append(" }");
buffer.append(" if (lineMeasurer.getPosition() < paragraph.getEndIndex())");
buffer.append(" {");
buffer.append(" layout = layout.getJustifiedLayout(formatWidth);");
buffer.append(" }");
buffer.append("");
buffer.append(" break;");
buffer.append(" }");
buffer.append(" case 3 :");
buffer.append(" {");
buffer.append(" drawPosX = formatWidth - layout.getAdvance();");
buffer.append(" break;");
buffer.append(" }");
buffer.append(" case 2 :");
buffer.append(" {");
buffer.append(" drawPosX = (formatWidth - layout.getAdvance()) / 2;");
buffer.append(" break;");
buffer.append(" }");
buffer.append(" case 1 :;");
buffer.append(" default :");
buffer.append(" {");
buffer.append(" drawPosX = 0;");
buffer.append(" }");
buffer.append(" }");
buffer.append("");
buffer.append(" draw(layout);");
buffer.append(" }");
buffer.append(" else");
buffer.append(" {");
buffer.append(" isMaxHeightReached = true;");
buffer.append(" }");
buffer.append(" }");
buffer.append(" }");

ctMethod.setBody(new String(buffer));

myCtClass.toClass();
} catch (NotFoundException e) {
e.printStackTrace();
} catch (CannotCompileException e) {
e.printStackTrace();
}

}

javassistを使って、既存のクラスのメソッドを置き換えるための手習い。 2008/02/20

狙いはjaspereportsのnet.sf.jasperreports.engine.export.renderParagraphの処理を変更したいということ。

対象としているのは、2.0.4
使用しているjavassistのバージョンは、3.6.0.GA

手順
(1)
まず、renderParagraphメソッドから中身をごっそりファイルにしておく。
(2)
1.でとったテキストを修正する、クラスはパッケージまでつけて、メソッドの引数は$1,$2,$3...としておく。
あと、きちんと確認がとれてないのですが、どうもcaseに他のクラスの定数をかくとどうもだめっぽい。これはあとで確認します※
(3)
javassistを使ってsetBodyして、toClassして凍らせる。このときにエラーがでないことをめざす。

(1)

{
AttributedCharacterIterator paragraph = null;

if (lastParagraphText == null)
{
paragraph =
new AttributedString(
" ",
new AttributedString(
allParagraphs,
lastParagraphStart,
lastParagraphStart + 1
).getIterator().getAttributes()
).getIterator();
}
else
{
paragraph =
new AttributedString(
allParagraphs,
lastParagraphStart,
lastParagraphStart + lastParagraphText.length()
).getIterator();
}

LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, LINE_BREAK_FONT_RENDER_CONTEXT);//grx.getFontRenderContext()

while (lineMeasurer.getPosition() < paragraph.getEndIndex() && !isMaxHeightReached)
{
//eugene fix - start
int startIndex = lineMeasurer.getPosition();
//eugene fix - end

TextLayout layout = lineMeasurer.nextLayout(formatWidth);

if (isMinimizePrinterJobSize)
{
//eugene fix - start
AttributedString tmpText =
new AttributedString(
paragraph,
startIndex,
startIndex + layout.getCharacterCount()
);
layout = new TextLayout(tmpText.getIterator(), grx.getFontRenderContext());
//eugene fix - end
}

float lineHeight = lineSpacingFactor *
maxFontSizeFinder.findMaxFontSize(
new AttributedString(
paragraph,
startIndex,
startIndex + layout.getCharacterCount()
).getIterator(),
fontSize
);

if (drawPosY + lineHeight <= textHeight)
{
drawPosY += lineHeight;

switch (horizontalAlignment)
{
case JRAlignment.HORIZONTAL_ALIGN_JUSTIFIED :
{
if (layout.isLeftToRight())
{
drawPosX = 0;
}
else
{
drawPosX = formatWidth - layout.getAdvance();
}
if (lineMeasurer.getPosition() < paragraph.getEndIndex())
{
layout = layout.getJustifiedLayout(formatWidth);
}

break;
}
case JRAlignment.HORIZONTAL_ALIGN_RIGHT :
{
drawPosX = formatWidth - layout.getAdvance();
break;
}
case JRAlignment.HORIZONTAL_ALIGN_CENTER :
{
drawPosX = (formatWidth - layout.getAdvance()) / 2;
break;
}
case JRAlignment.HORIZONTAL_ALIGN_LEFT :;
default :
{
drawPosX = 0;
}
}

draw(layout);
}
else
{
isMaxHeightReached = true;
}
}
}


(2)加工するためのコード
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class FileA {
public static void main(String[] args) throws IOException {

InputStream stream = FileA.class.getResourceAsStream("a.txt");
BufferedReader reader = new BufferedReader(
new InputStreamReader(stream));
String s = null;
while ((s = reader.readLine()) != null) {
String ss = s.replaceFirst("//.*$", "");
ss = ss.replaceAll("\"", "\\\\\"");

ss = ss.replaceAll("JRAlignment\\.HORIZONTAL_ALIGN_LEFT", "1");
ss = ss.replaceAll("JRAlignment\\.HORIZONTAL_ALIGN_CENTER", "2");
ss = ss.replaceAll("JRAlignment\\.HORIZONTAL_ALIGN_RIGHT", "3");
ss = ss.replaceAll("JRAlignment\\.HORIZONTAL_ALIGN_JUSTIFIED", "4");

ss = ss.replaceAll("JRAlignment", "net.sf.jasperreports.engine.JRAlignment");
ss = ss.replaceAll("LineBreakMeasurer", " java.awt.font.LineBreakMeasurer");
ss = ss.replaceAll("TextLayout", "java.awt.font.TextLayout");
ss = ss.replaceAll("AttributedCharacterIterator", " java.text.AttributedCharacterIterator");
ss = ss.replaceAll("AttributedString", "java.text.AttributedString");
ss = ss.replaceAll("JRAlignment", "net.sf.jasperreports.engine.JRAlignment");

ss = ss.replaceAll("allParagraphs", "\\$1");
ss = ss.replaceAll("lastParagraphStart", "\\$2");
ss = ss.replaceAll("lastParagraphText", "\\$3");
ss = ss.replaceAll("LINE_BREAK_FONT_RENDER_CONTEXT", "net.sf.jasperreports.engine.export.TextRenderer.LINE_BREAK_FONT_RENDER_CONTEXT");

// java.awt.Graphics2D;
// java.awt.font.FontRenderContext;
// java.awt.font.LineBreakMeasurer;
// java.awt.font.TextLayout;
// java.text.AttributedCharacterIterator;
// java.text.AttributedString;
// java.util.StringTokenizer;
//
// net.sf.jasperreports.engine.JRAlignment;
// net.sf.jasperreports.engine.util.JRProperties;
// net.sf.jasperreports.engine.util.JRStyledText;
// net.sf.jasperreports.engine.util.MaxFontSizeFinder;

System.out.printf("buffer.append(\"%s\");%n", ss);
}

}

}


(3)javassistを使ってメソッドの処理を変更。
import net.sf.jasperreports.engine.export.TextRenderer;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;

public class TestJavassist {

public static void main(String[] args) throws NotFoundException,
CannotCompileException {
a();
TextRenderer textRenderer = new TextRenderer(false);
}

static void a() throws NotFoundException, CannotCompileException {
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("net.sf.jasperreports.engine.export.TextRenderer");
CtMethod method = cc.getDeclaredMethod("renderParagraph");
StringBuffer buffer = new StringBuffer();
buffer.append(" {");
buffer.append(" java.text.AttributedCharacterIterator paragraph = null;");
buffer.append(" ");
buffer.append(" if ($3 == null)");
buffer.append(" {");
buffer.append(" paragraph = ");
buffer.append(" new java.text.AttributedString(");
buffer.append(" \" \",");
buffer.append(" new java.text.AttributedString(");
buffer.append(" $1, ");
buffer.append(" $2, ");
buffer.append(" $2 + 1");
buffer.append(" ).getIterator().getAttributes()");
buffer.append(" ).getIterator();");
buffer.append(" }");
buffer.append(" else");
buffer.append(" {");
buffer.append(" paragraph = ");
buffer.append(" new java.text.AttributedString(");
buffer.append(" $1, ");
buffer.append(" $2, ");
buffer.append(" $2 + $3.length()");
buffer.append(" ).getIterator();");
buffer.append(" }");
buffer.append("");
buffer.append(" java.awt.font.LineBreakMeasurer lineMeasurer = new java.awt.font.LineBreakMeasurer(paragraph, net.sf.jasperreports.engine.export.TextRenderer.LINE_BREAK_FONT_RENDER_CONTEXT);");
buffer.append(" ");
buffer.append(" while (lineMeasurer.getPosition() < paragraph.getEndIndex() && !isMaxHeightReached)");
buffer.append(" {");
buffer.append(" ");
buffer.append(" int startIndex = lineMeasurer.getPosition();");
buffer.append(" ");
buffer.append("");
buffer.append(" java.awt.font.TextLayout layout = lineMeasurer.nextLayout(formatWidth);");
buffer.append("");
buffer.append(" if (isMinimizePrinterJobSize)");
buffer.append(" {");
buffer.append(" ");
buffer.append(" java.text.AttributedString tmpText = ");
buffer.append(" new java.text.AttributedString(");
buffer.append(" paragraph, ");
buffer.append(" startIndex, ");
buffer.append(" startIndex + layout.getCharacterCount()");
buffer.append(" );");
buffer.append(" layout = new java.awt.font.TextLayout(tmpText.getIterator(), grx.getFontRenderContext());");
buffer.append(" ");
buffer.append(" }");
buffer.append("");
buffer.append(" float lineHeight = lineSpacingFactor * ");
buffer.append(" maxFontSizeFinder.findMaxFontSize(");
buffer.append(" new java.text.AttributedString(");
buffer.append(" paragraph, ");
buffer.append(" startIndex, ");
buffer.append(" startIndex + layout.getCharacterCount()");
buffer.append(" ).getIterator(),");
buffer.append(" fontSize");
buffer.append(" );");
buffer.append("");
buffer.append(" if (drawPosY + lineHeight <= textHeight)");
buffer.append(" {");
buffer.append(" drawPosY += lineHeight;");
buffer.append(" ");
buffer.append(" switch (horizontalAlignment)");
buffer.append(" {");
buffer.append(" case 4 :");
buffer.append(" {");
buffer.append(" if (layout.isLeftToRight())");
buffer.append(" {");
buffer.append(" drawPosX = 0;");
buffer.append(" }");
buffer.append(" else");
buffer.append(" {");
buffer.append(" drawPosX = formatWidth - layout.getAdvance();");
buffer.append(" }");
buffer.append(" if (lineMeasurer.getPosition() < paragraph.getEndIndex())");
buffer.append(" {");
buffer.append(" layout = layout.getJustifiedLayout(formatWidth);");
buffer.append(" }");
buffer.append("");
buffer.append(" break;");
buffer.append(" }");
buffer.append(" case 3 :");
buffer.append(" {");
buffer.append(" drawPosX = formatWidth - layout.getAdvance();");
buffer.append(" break;");
buffer.append(" }");
buffer.append(" case 2 :");
buffer.append(" {");
buffer.append(" drawPosX = (formatWidth - layout.getAdvance()) / 2;");
buffer.append(" break;");
buffer.append(" }");
buffer.append(" case 1 :;");
buffer.append(" default :");
buffer.append(" {");
buffer.append(" drawPosX = 0;");
buffer.append(" }");
buffer.append(" }");
buffer.append("");
buffer.append(" draw(layout);");
buffer.append(" }");
buffer.append(" else");
buffer.append(" {");
buffer.append(" isMaxHeightReached = true;");
buffer.append(" }");
buffer.append(" }");
buffer.append(" }");

method
.setBody(new String(buffer));
cc.toClass();
}
}

[javassist] もしかして制限? switch文のdefault 2008/02/20

javassistです。
バージョンは、3.6.0.GA です。

えーと、switch文でdefaultを使い方によっては制限がありそう。


Exception in thread "main" java.lang.NullPointerException
at javassist.compiler.CodeGen.atSwitchStmnt(CodeGen.java:539)


なんとなくわかったことは、
{ switch (0) {case 1:break;default:break;} }

という書き方はオッケーで、
{ switch (0) {case 1:default:break;} }

はだめっぽい。

caseとdefaultを続けて書くとNG

途中に;に入れるとよい

{ switch (0) {case 1:;default:break;} }

だとオッケーなよう。

以下、確認のためのコード
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;

public class CopyOfTestJavassist {

public static void main(String[] args) throws NotFoundException,
CannotCompileException {
a();
}

static void a() throws NotFoundException, CannotCompileException {
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("C");
CtMethod method = cc.getDeclaredMethod("m");
StringBuffer buffer = new StringBuffer();
//buffer.append("{ switch (0) {case 1:break;default:break;} }");//OK
//buffer.append("{ switch (0) {case 1:;default:break;} }");//OK
buffer.append("{ switch (0) {case 1:default:break;} }");//NG
method
.setBody(new String(buffer));
cc.toClass();

// Javaでは下記のswitch文は全部OK
switch (0) {case 1:break;default:break;}
switch (0) {case 1:;default:break;}
switch (0) {case 1:default:break;}
}
}

class C{
public void m(){

}
}

javassist メソッドの置き換えは、setBodyで。 2008/02/20


以前、javassistを使っていて、メソッドのふるまいをかえるのにわざわざremoveしてしまってましたが、単純にsetBodyを使って内容をごっそり置き換えたほうがらくですね。

CtClassクラスのremoveMethodを使わずに、CtMethodのsetBodyを使う。

で、setBodyで置き換えるメソッドがもらう引数は、$1,$2,$3....って感じでうけとれます。
それで、staticメソッドでなければ、フィールド変数にはそのまま名前でアクセスできます。
あと、他のクラスにアクセスするためには、パッケージ名まで書かないとだめです。

以下、適当にサンプル。

import a.A;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;

public class TestJavassist {

public static void main(String[] args) throws NotFoundException,
CannotCompileException {
a();
A a = new A();
a.m(17);
System.out.println(a);
}

static void a() throws NotFoundException, CannotCompileException {
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("a.A");
CtMethod method = cc.getDeclaredMethod("m");
method
.setBody("{ b.B b = new b.B(); x= 217 + f; System.out.println(b.xx);}");
cc.toClass();
}
}


package a;

public class A {
private int f = 17;
String s1 = "o_o!";
int x = 100;
int y =300;

public void m(int a){
x += a;
y += a;

}
public String toString(){
return " x:"+x + " y:" + y;
}

}


package b;

public class B {
public int xx= 177;

public int getX(){
return xx;
}
public B() {
}
}


うーん
javassistをプロジェクトに含めておくて、いざというときものすごく役にたつのではないかという予感がふつふつと。

[javascript]apply関数 2008/02/20

apply/JavaScriptリファレンス

あとでかく

[css]Internet Explorer6 では、display:inline;をしておく 2008/02/19

Internet Explorer6 では、display:inline;をしておく。
えーと、段組みレイアウトでおぼえておくべき項目っぽい。

float: left;
とかしていたら、Internet Explorer6対策用にdisplay:inline;

参考
スタイルシート・デザイン XHTML + CSSで実践するWeb標準デザイン講座
矢野 りん 益子 貴寛 こもり まさあき
4844359045

p.145 段組みレイアウト問題

[java] 文字列からjava.util.Dateに変換します。そのときに大目にみません。 2008/02/19

yyyyMMddフォーマットの文字列をjava.util.Dateに変換します。
java.text.SimpleDateFormatを使用しています。
それでSimpleDateFormatのメソッドで、「大目に」みるメソッドをfalseにすることを忘れてはいけません。

大目にみてしまうと
20081717
というの値もDateに変換してしまいます。

lenient
大目{おおめ}に見た、情け深い


public void setLenient(boolean lenient)

日付/時刻解析を厳密に行うかどうかを設定します。厳密でない解析では、解析機能は、ヒューリスティックな方法を使って、このオブジェクトのフォーマットと完全には一致しない入力を解釈することがあります。厳密な解析では、入力はこのオブジェクトのフォーマットと一致する必要があります。javadoc6




static Date toDate(String yyyyMMdd){
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
try {
simpleDateFormat.setLenient(false);
return simpleDateFormat.parse(yyyyMMdd);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}

IE(Internet Explorer)について思うこと 2008/02/18

お仕事の大半の時間はWindows上で開発しています。
個人的な開発やブログはmac osx上で行っています。

ブラウザを使っている時間がとても長いのですが、いつのころからかIEを使うことがなくなりました。
macでIEが5で止まってバージョンアップがなくなったのでプライベートでは決して使うことがないブラウザになりました。

それで、このプログラマメモ2にアクセスする人の53%IEです。約半数です。
そのなかで、バージョン6の人は79.80%です。
バージョン7.0の人は19.88%です。
バージョン5の人はほとんどいませんでした。

firefoxとsafariでcssをちょこちょこいじっていてうまくいったと思ってもIEでみるとがっかりすることばかりです。
pngで透明サポートもそうですし、他にいろいろあります。



background-position、パディング、マージンの振る舞いが最近の悩みのたねです。

まあこつこつやっていくしかないですが...
Orz...

参考

過去の記事のほりおこし アイデアレベル 2008/02/17

せっかくBloggerにラベル(タグ)の機能があるので、さらに利用できないかなぁと思いました。
過去の記事が埋没するのをほりおこして、新しい記事と関連づけられたらよさげです。



データをキャッシュさせたり、関連記事を作成するためのルールをいろいろ拡張したりしたいので、サーバにそのロジックをもたせてもいいかなぁと画策中です。

HttpServletResponse#getOutputStream()はcloseを明示的にしなくてもいいといことで. 2008/02/16

天使やカイザーと呼ばれて: HttpServletResponse#getOutputStream()したストリームは自分でclose()するのか?
という記事で、アプリケーションサーバー(サーブレットコンテナ)まかせでいい感じ。

Servlet API とかの仕様を読まないとわからないことのようですね。

[PKU] 1163 -- The Triangle - キャッシュして - 再チャレンジ 2008/02/14



再チャレンジです。

Short Coding本を参考にしました。
Short Coding ~職人達の技法~
Ozy やねうらお
4839925232
p.192 アルゴリズムでキメる
に載っていました。
すごいの一言。
とても参考になりました。

あわせて、p.195のコラムにあった「計算量のオーダ」は読むべしべしべしでした。

で、わかったことは、キャッシュを使って同じ計算を回避するということ。
一応サブミットして、acceptedされました。

package p1163;

import java.util.Scanner;

public class Main {

public static void main(String[] args) {
a();
}


static void a() {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();

list = new int[n][];
memo = new int[n][];
for (int i = 0; i < n; i++) {
int[] js = new int[i+1];
int[] mm = new int[i+1];
for (int j = 0; j <= i; j++) {
js[j] = scanner.nextInt();
mm[j] = -1;
}
list[i] = js;
memo[i] = mm;
}

int max = max(list[0][0], 0, 1);
System.out.println(max);
}

static int[][] list;
static int[][] memo;
static int n = 0;

static int max(int c, int p, int pos) {

if (n <= pos)
return c;
int l = memo[pos][p];
int r = memo[pos][p + 1];
if(l == -1){
memo[pos][p] = list[pos][p] + max(c, p, pos + 1);
l = memo[pos][p];
}
if(r == -1){
memo[pos][p + 1] = list[pos][p + 1] + max(c, p + 1, pos + 1);
r = memo[pos][p + 1];
}

return l < r ? r : l;
}

}


参考
[PKU3176] - Cozy Ozy

[PKU] 1163 -- The Triangle - 単純に再帰させるだけではだめでした。 2008/02/14



チャレンジしてみました。

ちょっと考えて書いたコードだったのですが、案の定だめでした。

これぐらいだったら平気なのですが、最大100ですと、計算量が、2100となるらしくだめ。
5だと25

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5


以下だめコード。
package p1163;

import java.util.Scanner;

public class Main {

public static void main(String[] args) {
a();
}

static void a() {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();

list = new int[n][];
for (int i = 0; i < n; i++) {
int[] js = new int[i+1];

for (int j = 0; j <= i; j++) {
js[j] = scanner.nextInt();
}
list[i] = js;
}

int max = max(list[0][0], 0, 1);
System.out.println(max);
}

static int[][] list;
static int n = 0;

static int max(int c, int p, int pos) {

if (n <= pos)
return c;
int l = list[pos][p] + max(c, p, pos + 1);
int r = list[pos][p + 1] + max(c, p + 1, pos + 1);

return l < r ? r : l;
}

}

[java] SimpleDateFormatを使って、日付フォーマット。 2008/02/13

Javaです。
年に何度か、コーディングしないといけなくなる日付フォーマット関連です。

あるシステムでは日付を1966/04/01というふうに扱います。
こちらでは、19660401として扱いたいのですが...
ということが多々あります。

ところで、1966/04/01なら/をとりのぞけば、19660401になりますが、1966/4/1とかだとなんか面倒です。
この辺、/で区切って、一桁だったら頭に0つけるとかでもありですね。


java.text.SimpleDateFormatです。

yyyy/MM/dd
というフォーマットを使ってみました。
parseというメソッドで、Date型に
formatというメソッド、文字列表現に。

小文字のmmだと「分」
大文字のDDだと「年における日」
となります。

package datefromat;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class TestA {

public static void main(String[] args) throws ParseException {
String d = "1966/4/1";
String d2 = "1966/04/01";
System.out.println(date("yyyy/MM/dd", d));
System.out.println(date("yyyy/MM/dd", d2));

if(date("yyyy/MM/dd", d).equals(date("yyyy/MM/dd", d2))){
System.out.println("OK");
}

System.out.println(toyyyyMMdd("yyyy/MM/dd", d));
System.out.println(toyyyyMMdd("yyyy/MM/dd", d2));
}

static public Date date(String format, String d) throws ParseException{
Date date = new SimpleDateFormat(format).parse(d);
return date;
}

static public String toyyyyMMdd(String format, String d) throws ParseException{
Date date = new SimpleDateFormat(format).parse(d);
return new SimpleDateFormat("yyyyMMdd").format(date);
}
}

java ファイルのコピーや移動のコードが面倒ならCommons使います。 2008/02/13

ファイルのコピーや移動のコードが面倒なら、Commons IO - Homeを使うのも手です。

おそらく問題ないと思います。

[PKU] 3117 -- World Cupは鶴亀算 2008/02/10


ひさしぶりにチャレンジ。

で、問題文みて、頭がくらくらして、ああと思って、グーグルさんにお聞きして、ヒントを得て、サブミット。

鶴亀算と一言書いていた人がいて、長い間考えて、そうかもと思った次第。

鶴亀算って全部が鶴だったら、そこから、考える。

それで、勝ったら3点、引き分けだったら1点、負けたら0点なので、全て勝ったらと考えると
3 * the number of played matchesで全てのマッチにおいて、引き分けがなかった場合の、えーと、かならずどこかのチームが勝った場合の得点合計が求められる。

で、
(3 * the number of played matches) - 実際の得点合計
から、引き分けだった回数が求められる(引き分けだと点数が1点なのでそのまま回数と考えられる)

package p3117;

import java.util.Scanner;

public class Main {
public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);

while (true) {
int t = scanner.nextInt();
int m = scanner.nextInt();
if (t == 0 && m == 0)
break;
int c = 0;
for(int i=0;i<t;i++){
scanner.next();
c += scanner.nextInt();
}
System.out.println((3*m)-c);
}
}
}



参考

失敗、cometを使ってtail -fの内容を送りたい。 2008/02/03

クライアントでサーバー側のログをみたいということで、tomcat6に入っているcometさんの機能を使えないかなというわけで、頭をひねってみたのでした。

安直にtail -fをコマンド実行して標準出力の内容をせっせっとcomet使って、クライアントに送ればいいじゃんと思ったわけです。

方々を参考にして簡単に実装してみましたが、結果は、「もっと工夫しないとだめ」です。

工夫する必要がある箇所は、ずばりログのとりこぼしがないようにしないといけないところです。

ログのとりこぼしがないようにするためには、どこまでのログをクライアントは受信されたのかという情報をもたせないとできない。それで、その情報をもとにして、サーバーがログを送ってあげる。

あと、CometサーバーとCometクライアントの仕組みがよくわからないです。
基本はLong Pollingなんだというキーワード的にはわかってるんですが....

サーバー側がずーと書き込めるストリームをもちつづけて、だらだら書けば、クライアントに表示できるのであれば簡単だなぁと思ったのですが、その場合のクライアントの実装が思いつかないので、XmlHttpRequest方式(たぶん)で。

しかし、サーバー側の書き込みが終了したということを通知する方法がわからなかったので、BEGINで受け取ったイベントに対してTIMEOUTを設定して、必ずその時間がたったらクライアントはレスポンスを受け取り、処理をして再接続という実装(のつもり)にしてみました。

すぐにクライアントに反映されないので、メリットが感じられないような...

ログのように常に変化し続けるものを表示する場合ってiframe方式(たぶん)がいいのかもしれない。



理解不足、曲解、だめだめですが、とりあえず晒しておくことにします。

<html>
<head>
<script type="text/javascript" src="jquery-1.2.2.min.js"></script>
<script type="text/javascript" >
var isStop = false;
var cash_log1 ="";
var cash_log2 ="";
var cnt =0;
function oo(){
$.ajax({
url: 'http://localhost:8090/examples/tail',
type: 'POST',
dataType: "text",
timeout: 60000,
error: function(){
if(isStop) return;
alert('Error loading text document');
},
success: function(data){

if(isStop) return;
if(!(0 < data.length)){
setTimeout(oo, 1);
return;
}

cash_log1 = cash_log2;
cash_log2 = data;

$('#pp').val(cash_log1 + cash_log2);
setTimeout(oo, 1);
}
});


}
</script>
</head>
<body onload="oo();">
<input type="button" onclick="javascript:isStop=true;" value="stop"/>
<input type="button" onclick="javascript:isStop=false;oo();" value="start"/>
<div id="p"></div>
<textarea id="pp" cols=100 rows=10>
</textarea>
</body>
</html>


import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;

import org.apache.catalina.CometEvent;
import org.apache.catalina.CometProcessor;

public class TailServlet extends HttpServlet implements CometProcessor {

private static final long serialVersionUID = 1L;
protected ArrayList<CometEvent> connections = new ArrayList<CometEvent>();
protected MessageSender messageSender = null;

public void init() throws ServletException {
messageSender = new MessageSender(getInitParameter("targetFile"));
Thread messageSenderThread = new Thread(messageSender, "MessageSender["
+ getServletContext().getContextPath() + "]");
messageSenderThread.setDaemon(true);
messageSenderThread.start();
}

public void destroy() {
connections.clear();
messageSender.stop();
messageSender = null;
}

public void event(CometEvent event) throws IOException, ServletException {

HttpServletRequest request = event.getHttpServletRequest();
if (event.getEventType() == CometEvent.EventType.BEGIN) {

// timeoutを起こしてクライアントにいったんデータを返す。
event.setTimeout(new Integer(5000));
log("Begin for session: " + request.getSession(true).getId());
log(connections.toString());
synchronized (connections) {
connections.add(event);
}

} else if (event.getEventType() == CometEvent.EventType.ERROR) {
log("Error for session: " + request.getSession(true).getId());
log("EventSubType: " + event.getEventSubType());
synchronized (connections) {
boolean isRemoved = connections.remove(event);
log(" isRemoved:" + isRemoved);
}
event.close();
} else if (event.getEventType() == CometEvent.EventType.END) {
log("End for session: " + request.getSession(true).getId());
log("EventSubType: " + event.getEventSubType());
synchronized (connections) {
boolean isRemoved = connections.remove(event);
log(" isRemoved:" + isRemoved);
}
event.close();
} else if (event.getEventType() == CometEvent.EventType.READ) {
}
}

public class MessageSender implements Runnable {
protected boolean running = true;
String targetFile;

public MessageSender(String targetFile) {
this.targetFile = targetFile;
}

public void stop() {
running = false;
}

public void run() {
String command = "/usr/bin/tail -f " + targetFile;
Runtime runtime = Runtime.getRuntime();
Process process = null;
try {
process = runtime.exec(command);
InputStream in = process.getInputStream();
Scanner scanner = new Scanner(in);

while (scanner.hasNext() && running) {
String s = scanner.nextLine();
// log("o_o!==>" + s);
synchronized (connections) {
Iterator<CometEvent> iterator = connections.iterator();
while (iterator.hasNext()) {
CometEvent event = (CometEvent) iterator.next();
try {

PrintWriter writer = event
.getHttpServletResponse().getWriter();
writer.println(s);
writer.flush();

} catch (IOException e) {
log("IOExeption sending message", e);
} catch (UnsupportedOperationException e) {
e.printStackTrace();
}

}

}
}

} catch (IOException e1) {
e1.printStackTrace();
} finally {
if (process != null) {
try {
process.getErrorStream().close();
} catch (IOException e) {
}
try {
process.getInputStream().close();
} catch (IOException e) {
}
try {
process.getOutputStream().close();
} catch (IOException e) {
}
}
running = false;
}

}
}

}

jqueryを使って、<textarea>値</textarea>の値の読み書きです。 2008/02/03

jqueryを使って、<textarea>値</textarea>の値の読み書きです。

読み
s = $('#id').val();

書き
$('#id').val(値);

でいいようです。

現時点でのTomcat6でcometするときには、server.xmlをprotocol="org.apache.coyote.http11.Http11NioProtocol"するっぽい。 2008/02/02

現時点でのTomcat6でcometさんするときには、server.xmlをprotocol="org.apache.coyote.http11.Http11NioProtocol"するっぽい。
というかします。

もうひとつ別のAPRというものを導入するやり方もあるようです。

で下記のリンク参考


cometってajaxがないといまのところ効果的に使えないと思うのですがどうなんでしょう。「Ajaxを超える」といういいまわしって誤解を生みそうな気がしますが...

tailコマンドを使ってjava経由でtailもどき 2008/02/02

tailもどきをjavaで実装するのが面倒なら、はじめからコマンドを使うってのもありかもしれない。

windowsならcygwinにあるのを使えば、たいていのosにあると思われるtailコマンドを使えるわけなのですな。

processを使って標準入力を受けたものをそのまま標準出力しています。

import java.io.IOException;
import java.io.InputStream;

public class A_TAIL {

/**
* @param args
*/
public static void main(String[] args) {

String command = "/usr/bin/tail -f /Users/xxxx/tmp/z.txt";
exec(command);

}

protected static boolean exec(String command) {

Process process = null;

try {

Runtime runtime = Runtime.getRuntime();
process = runtime.exec(command);
InputStream in = process.getInputStream();
int c;
while ((c = in.read()) != -1) {
System.out.print((char) c);
}

} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
if (process != null) {
try {
process.getErrorStream().close();
} catch (IOException e) {
}
try {
process.getInputStream().close();
} catch (IOException e) {
}
try {
process.getOutputStream().close();
} catch (IOException e) {
}
}
}

return true;
}
}

勘違いしていました。tail.c 2008/02/02

えーと、勘違いしてました。
tailコマンドの-fオプションでファイルの更新がみれるのは、os側に何かコールバック関数みたいのを設定すれば、os側から更新情報が伝わってくるのかと...

えーと、そうではなかったです。

tail.cのソースです。


sleep(1)して、fstat() 関数を使って、ループでぐるぐるして、変化があったら画面にダンプしてまた、sleep(1)して、fstat() 関数を使って、ループでぐるぐるして、以下同。

だとすると、Javaでやったとしてもループでぐるぐるして、sleepして変化があったら読んで、以下同って感じになるのかなぁ。

下のような実装もあるわけです。この実装ってtail.cと似てますね。


えーん、ずーと勘違いしてた
Orz...

「Java 仮想マシンが利用可能なプロセッサの数」を得る - java.lang.RuntimeののavailableProcessorsメソッド 2008/02/02

「Java 仮想マシンが利用可能なプロセッサの数」を得るのに、java.lang.RuntimeのavailableProcessorsが使えるようです。

それで、javadocには下記のようにあります。

Java 仮想マシンが利用可能なプロセッサの数を返します。

この値は、仮想マシンへの特定の呼び出し中に変更される可能性があります。このため、利用可能なプロセッサ数に影響を受けるアプリケーションは、このプロパティをときどきポーリングして、リソース使用法を調整する必要があります。javadoc1.5


実行は、MacBookです。




int n = Runtime.getRuntime().availableProcessors();
System.out.println(System.getProperty("os.name"));
System.out.println(System.getProperty("os.arch"));
System.out.println(System.getProperty("sun.cpu.endian"));
System.out.println("availableProcessors:" + n);


結果
Mac OS X
i386
little
availableProcessors:2


はて、プロセッサの数を得たとしてどう利用しよう.....

内部クラス 匿名クラス 無名クラス 2008/02/01

Javaです。
よく混乱するのでメモ
いまさら感が漂いますが。

クラスの中で定義しているものは全部インナークラスでいいのではないかという気がしてきましたが、



あっなるほど、staticなものはインナークラスとはいわないのか...

自分の名をもたないクラスを匿名クラス(無名クラス)という。