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

せいき表現練習 - 最短一致 2009/06/29

Javaです。正規表現です。わかりづらいですが最短一致です。

以下のようなもんもんがありまして、このテキストからSQLだけとりだしたいわけです。

sql = "
select *
from a
where a.i = ?
";

sql = "
select *
from b
where b.i = ?
";


単純に「sql=」からはじまって「;」でおわってるなぁっていうことがわかります。
sql=.*;

とかしちゃうと、一番最後の「;」までマッチしてしまいますね。
ずばり、これが最長一致です。たぶん。

それだと目的とあわないです。「sql」からはじまって、最初に出現した「;」までマッチさせたいわけですから、ここで最短一致が使えるわけです。

下のように書くようです。
.*?


というわけで、以下Javaコード。DOTALLを忘れずに。
package a;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test_正規表現_最短一致 {

public static byte[] getBytes(InputStream in) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
int len = 0;
byte[] bs = new byte[8192];
while ((len = in.read(bs)) != -1) {
outputStream.write(bs, 0, len);
outputStream.flush();
}
outputStream.close();
} finally {
in.close();
}
return outputStream.toByteArray();
}

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

Test_正規表現_最短一致 t = new Test_正規表現_最短一致();

String s = new String(getBytes(t.getClass().getResourceAsStream(
"txt最短一致.txt")));
t.a(s);
}

void a(String s) {

Pattern pattern = Pattern.compile("\\s*sql =\\s*\"(.*)\";", Pattern.DOTALL);

Matcher matcher = pattern.matcher(s);
int cnt = 0;
while (matcher.find()) {
System.out.println("*** " + ++cnt);
System.out.println(matcher.group(1));
}

}
}

jdbc IN句 2009/06/28

Javaです。JDBCです。PreparedStatementです。ふと、whereで使うIN句で、?に配列(リスト)を指定できないのかしらと思ったわけです。
どういうことかといいますと、

SELECT * FROM 品番 WHERE 品番 IN('A001')

って感じのSQLで、さらに、
SELECT * FROM 品番 WHERE 品番 IN('A001', 'A003', 'A011', 'A087')

って感じになるときに、PreparedStatementで、
SELECT * FROM 品番 WHERE 品番 IN(?, ?, ?, ?)

って指定するのではなく、ずばり、
SELECT * FROM 品番 WHERE 品番 IN(?)

はてな一個でできないかということです。

なんかできそうだよなーと思いつつもできないかもなぁという思いありつつ調べたのですが、結論は、おそらく《できない》、です。

似たように考えるひとびとは結構いるらしい、検索すると、でてきます。
Java以外の言語のAPI、ライブラリ−だとあるかもしれませんが...

その都度、SQLを組み立てればよいですが、組立てる場合、まあ、そのSQLとして問題がないように気を使う必要がでてきますね。

例えば、はてなを二個連結しするとできるとか、配列(リスト)を展開してくれるとかってはどうでしょうかねー
SELECT * FROM 品番 WHERE 品番 IN(??)





H2を使って試したコードです。
150000連結させてみました。

package a;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class Test_SelectIn {

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

static void a() {

try {
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:~/test",
"sa", "");

// 'a001', 'a001'
String sql = "select * from 品番 where 品番 IN(@R@)";
List<String> list = new ArrayList<String>();
list.add("a001");
for (int i = 0; i < 150000; i++) {
list.add("a" + i);
}
StringBuilder sb = new StringBuilder();
for (String s : list) {
sb.append("?,");
}

if (!(sb.length() - 1 < 0) && sb.charAt(sb.length() - 1) == ',') {
sb.deleteCharAt(sb.length() - 1);
}
sql = sql.replace("@R@", sb);
PreparedStatement ps = conn.prepareStatement(sql);
for (int i = 0; i < list.size(); i++) {

}
int pos = 1;
for (String s : list) {
ps.setString(pos++, s);
}
System.out.println(ps.toString());
ResultSet resultSet = ps.executeQuery();
while (resultSet.next()) {
System.out.println(resultSet.toString());
}

conn.close();

} catch (Exception e) {
e.printStackTrace();
}

}
}

「ファインダーを起動して指定した階層のディレクトリを開く」です。 2009/06/27

Javaです。mac osxです。

「ファインダーを起動して指定した階層のディレクトリを開く」です。
何かとOS側と連携したいとき便利です。



windowsではopenではなく、explore.exeを指定します。

package aaa;

import java.io.File;
import java.io.IOException;

public class OSX_command {

public static void main(String[] args) throws IOException, InterruptedException {
open(new File("/tmp1"));
}

static void open(File f) throws IOException, InterruptedException{

Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("open " + f.getAbsolutePath());

process.waitFor();
System.out.println(process.exitValue());
}
}

JTextPaneで行をおりかえさない。 2009/06/24

Javaです。Swingです。JTextPaneです。

もとネタは下記



折り返さないことはできたのですが、スクロールペインが反応してくれなくて、うーん、と悩んだわけです。
で、JTextArea(BasicTextAreaUI)の実装をぱらぱらみてて、JTextAreaは、WrappedPlainViewというものを使っていて、よくよくみると折り返し(wrap)しない場合は、javax.swing.text.PlainViewを使ってました。

Swing - Stretching background colour across whole JTextPane for one line of textでは、いろいろスクロールペインを効かせるためのコードがのってるようでしたが、いっそPlainViewを使ってしまえということで、下記のコード。



package a;

import javax.swing.*;
import javax.swing.text.*;

/**
*
* http://forums.sun.com/thread.jspa?threadID=622683
*
*
*/
public class NoWrapEditorKit extends StyledEditorKit {
public ViewFactory getViewFactory() {
return new StyledViewFactory();
}

static class StyledViewFactory implements ViewFactory {
public View create(Element elem) {
String kind = elem.getName();

if (kind != null) {
if (kind.equals(AbstractDocument.ContentElementName)) {
return new LabelView(elem);
} else if (kind.equals(AbstractDocument.ParagraphElementName)) {
return new ParagraphView(elem);
} else if (kind.equals(AbstractDocument.SectionElementName)) {
// return new NoWrapBoxView(elem, View.Y_AXIS);
// return new WrappedPlainView(elem, false);
return new PlainView(elem);
} else if (kind.equals(StyleConstants.ComponentElementName)) {
return new ComponentView(elem);
} else if (kind.equals(StyleConstants.IconElementName)) {
return new IconView(elem);
}
}

return new LabelView(elem);
}
}

static class NoWrapBoxView extends BoxView {
public NoWrapBoxView(Element elem, int axis) {
super(elem, axis);
}

public void layout(int width, int height) {
super.layout(1024, height);
}
}

public static void main(String[] args) throws Exception {
JTextPane textPane = new JTextPane();
textPane.setEditorKit(new NoWrapEditorKit());

JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(textPane));
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

リンク収集 - Mozilla Java Html Parserを使ってみる。 2009/06/13

HTMLに存在するリンク(aタグのhrefがあるもの)をひろいだしたいと思ったのでした。
htmlパーサーはいろいろあるようですが、Mozilla Java Html Parserを使ってみます。



実は、以前、試そうとして、ネイティブライブラリを使うことを知って、環境変数の設定が面倒だと思い、使わずじまいでした。

今回はosx上のEclipse上で動かしてみます。

僕の環境変数の設定は、実行する際の「Run configurations」のEnvironmentを利用しました。
mac osxの場合は、DYLD_LIBRARY_PATHを設定します。



以下コードです。
package aaa;

import static quicklunch.e2.goodies.utils.ObjectUtils.eq;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.dappit.Dapper.parser.MozillaParser;

public class A_リンク収集 {

public static void main(String[] args) throws Exception {
test();
}

static String get_html(String surl, String enc)
throws MalformedURLException, IOException {
URLConnection connection = new URL(surl).openConnection();
connection.connect();
BufferedInputStream in = new BufferedInputStream(
(InputStream) connection.getContent());

return get(in, enc);
}

public static String get(InputStream in, String enc) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
int len = 0;
byte[] bs = new byte[8192];
while ((len = in.read(bs)) != -1) {
outputStream.write(bs, 0, len);
outputStream.flush();
}
outputStream.close();
} finally {
in.close();
}
String s = new String(outputStream.toByteArray(), enc);
return s;
}

public static String get_file(String filepath, String enc)
throws IOException {

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
filepath));
return get(bis, enc);
}

static void test() throws Exception {
String s = get_html("http://deiji.jp", "utf-8");
MozillaParser.init();
Document document = new MozillaParser().parse(s);
System.out.println(getLink((Node) document.getDocumentElement()));
}

public static class Link {
String title;
String link;

public Link(String title, String link) {
this.title = title;
this.link = link;
}

public String toString() {
return title + ":" + link;
}
}

public static List<Link> getLink(Node node) {
List<Link> list = new ArrayList<Link>();
switch (node.getNodeType()) {
case Node.ELEMENT_NODE:
NamedNodeMap attrs = node.getAttributes();
if (eq(node.getNodeName(), "a")
&& attrs.getNamedItem("href") != null) {
String link = attrs.getNamedItem("href").getNodeValue();
NodeList nl = node.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node n2 = nl.item(i);
if (n2.getNodeType() == Node.TEXT_NODE) {
list.add(new Link(n2.getNodeValue(), link));
}
}
}

for (Node child = node.getFirstChild(); child != null; child = child
.getNextSibling()) {
list.addAll(getLink(child));
}
}
return list;
}
}