import java.io.*; import javax.xml.parsers.*; import org.w3c.dom.*; File f; // 파싱할 파일. 어느 곳에선가 초기화 되었다고 가정하자 // DOM 파서를 만들기 위한 팩토리 오브젝트를 만든다 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 이제 패토리를 이용해서 DOM 파서를 만들자 (이것은 DocumentBuilder라고도 알려져 있다) DocumentBuilder parser = factory.newDocumentBuilder(); // 파일을 파싱해서 그 내용을 나타내는 문서 트리를 작성한다 Document document = parser.parse(f); //9. XML 변환태그를 포함하는 모든 목록을 요청한다 NodeList sections = document.getElementsByTagName("sect1"); // 요소를 한번에 하나씩 루프를 돌리고 태그의 내용을 추출한다 int numSections = sections.getLength(); for(int i = 0; i < numSections; i++) { Element section = (Element)sections.item(i); // A // 선택된 ( 요소)의 첫번째 자식 요소를 찾고, 포함하고 있는 본문을 출력한다 Node title = section.getFirstChild(); while(title != null && title.getNodeType() != Node.ELEMENT_NODE) title = title.getNextSibling(); // 이 요소의 자식 텍스트 노드에 포함된 본문을 출력한다 if (title!=null) System.out.println(title.getFirstChild().getNodeValue()); }
참고 도서 |
import javax.xml.transform.*; import javax.xml.transform.dom.*; import javax.xml.transform.stream.*; import org.w3c.dom.*; File xsltfile; // XSLT 파일로 어딘가에서 초기화되었다 Document document; // 이미 이 DOM문서를 만들었거나 읽었다고 가정하자 Source xsltSource = new StreamSource(xsltfile); // 변환을 위한 자원 Source source = new DOMSource(document); 변환될 문서 Result result = new StreamResult(System.out); // 결과문서를 저장할 곳 // 팩토리 오브젝트에서 시작 TransformerFactory tf = TransformerFactory.newInstance(); // 팩토리를 이용해서 XSLT 파일을 읽어서 텔플릿 오브젝트에 넣기 Templates transformation = tf.newTemplates(xsltSource); // 템플릿 오브젝트로부터 변환 오브젝트를 생성 Transformer transformer = transformation.newTransformer(); // 마지막으로 변환을 수행 transformer.transform(source, result);8. Preferences
// TextEditor 클래스를 포함하는 패키지의 사용자와 시스템 preferences에 대한 Preferences 오브젝트를 가져온다. Preferences userprefs = Preferences.userNodeForPackage(TextEditor.class); Preferences sysprefs = Preferences.systemNodeForPackage(TextEditor.class); // 정수값을 갖는 사용자 preferences를 조회한다. // 항상 기본 값을 전달하고 있음에 주목 int width = userprefs.getInt("width", 80); // 기본값으로 시스템 preferences에서 사용하는 사용자 preference를 조회하자. String dictionary = userprefs.get("dictionary" sysprefs.get("dictionary", "default_dictionary"));7. Logging
import java.util.logging.*; // 현패키지명을 따라 Logger오브젝트 이름을 가져온다 Logger logger = Logger.getLogger("com.davidflanagan.servers.pop"); logger.info("Starting server."); // 로그정보메시지를 남긴다. ServerSocket ss; try { ss = new ServerSocket(110); } catch(Exception e) { // 예외사항 로그 logger.log(Level.SEVERE, "Can"t bind port 110", e); // 복잡한 로그 메시지 logger.warning("Exiting"); // 간단한 경고 return; } logger.fine("got server socket"); // 낮은 수준의 충분히 자세한 디버깅 메시지6. 보안 소켓과 HTTPS
import javax.net.ssl.*; import java.io.*; // SSL 소켓을 생성하기 위하여 SocketFactory 오브젝트를 가져온다. SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); // 서버의httpS 포트(포트 443)에 연결될 보안 소켓을 생성한다. SSLSocket sslsock = (SSLSocket) factory.createSocket(hostname, 443); // 웹서버가 제공하는 인증서를 가져온다. 이 작업은 서버가 인증서를 제공하지 않을 때를 대비해서 예외 처리될 수 있다. 인증서의 발급자를 보고 신뢰여부를 판단한다. SSLSession session = sslsock.getSession(); X509Certificate cert = (X509Certificate)session.getPeerCertificates()[0]; String issuer = cert.getIssuerDN().getName(); // 인증서를 믿을 수 있다고 가정하면, 이제 일반적인 java.net.Socket 오브젝트를 사용하듯이 생성된 소켓을 사용한다. 하던데로HTTP 요청을 보내고 반응을 읽는다. PrintWriter out = new PrintWriter(sslsock.getOutputStream()); out.print("GET " + args[1] + "http/1.0\r\n\r\n"); out.flush(); // 다음으로 서버의 반응을 읽고 콘솔에 출력한다.. BufferedReader in = new BufferedReader(new InputStreamReader(sslsock.getInputStream())); String line; while((line = in.readLine()) != null) System.out.println(line); // 마지막으로 소켓을 닫는다. sslsock.close();5. LinkedHashMap
public class LRUCache extends java.util.LinkedHashMap { public LRUCache(int maxsize) { super(maxsize*4/3 + 1, 0.75f, true); this.maxsize = maxsize; } protected int maxsize; protected boolean removeEldestEntry() { return size() > maxsize; } }4, 파일 채널
import java.io.*; // FileInputStream import java.nio.*; // ByteBuffer import java.nio.channels.*; // FileChannel // FileChannel을 생성하고 파일의 크기를 가져오고 ByteBuffer에 파일을 매핑한다. FileChannel in = new FileInputStream("test.data").getChannel(); int filesize = (int)in.size(); ByteBuffer mappedfile = in.map(FileChannel.MapMode.READ_ONLY, 0, filesize); // 파일은 고정크기의 바이너리 데이터 레코드를 가지고 있다고 가정하자 static final int RECORDSIZE = 80; // 각 레코드의 크기 int recordNumber = 1; // 우리가 읽고자 하는 레코드 byte[] recorddata = new byte[RECORDSIZE]; // 레코드 데이터를 가진 배열 mappedfile.position(recordNumber*RECORDSIZE); // 원하는 레코드를 시작한다. mappedfile.get(recorddata); // 버퍼로부터 배열을 채운다.메모리 매핑은 상당한 재미를 주지만 그에 따른 비용을 지불해야 한다. 전형적인 자바구축에서 일반적으로 작은 크기의 파일(대략 100 킬로바이트 미만의 파일)을 읽을 때는 메모리 매핑을 쓰지 않고 그냥 읽어 오는 것이 훨씬 효율적이다.
FileChannel in; // 어딘가에서 초기화 되었다 FileLock lock = in.lock(recordNumber*RECORDSIZE, // 잠금 시작 부분 RECORDSIZE, // 잠금 부분의 길이 true); // 공유 잠금: 동시 갱신 금지 // 원하는 레코드를 읽고나서 잠금을 해제한다. lock.release()3. Non-Blocking I/O
import java.nio.channels.*; import java.util.*; // 모든 클라이언트 접속을 모니터링하는 selector오브젝트를 생성 Selector selector = Selector.open(); // 새로운 non-blocking erverSocketChannel을 생성하고 8000포트에 바인딩 시키고 Selector와 함께 등록한다. ServerSocketChannel server = ServerSocketChannel.open(); // 채널을 열고 server.configureBlocking(false); // Non-blocking server.socket().bind(new java.net.InetSocketAddress(8000)); // 포트 바인딩 SelectionKey serverkey = server.register(selector, SelectionKey.OP_ACCEPT); for(;;) { // 메인 서버 루프. 서버는 영원히 동작한다. // 등록된 채널의 중 하나에 활동이 있을 때 까지 호출은 block된다. 이것이 non-blocking I/O에 핵심적인 방법이다. selector.select(); // I/O에 준비된 모든 채널에 대한 SelectionKey 오브젝트를 가지고 있는 java.util.Set을 가져온다. Set keys = selector.selectedKeys(); // java.util.Iterator을 이용하여 선택된 키에 대해 루프를 실행한다. for(Iterator i = keys.iterator(); i.hasNext(); ) { SelectionKey key = (SelectionKey) i.next(); i.remove(); // 선택된 키 집합에서 키를 삭제한다. // ServerSocketChannle에 등록할 때 키가 SelectionKey인지 검증한다. if (key == serverkey) { // ServerSocketChannel에서 활동은 클라이언트가 서버와 접속하려고 시도하는 것을 의미한다. if (key.isAcceptable()) { // 클라이언트 접속을 받는다. SocketChannel client = server.accept(); // 클라이언트 채널을 non-blocking 모드로 할당한다. client.configureBlocking(false); // 클라이언트 채널을 Selector 오브젝트를 가지고 등록한다. SelectionKey clientkey = client.register(selector, SelectionKey.OP_READ); } } else { // 다른 경우, 클라이언트 채널에는 활동이 존재해야하고 읽어드릴 // 데이터가 있는지 이중 검증한다. if (!key.isReadable()) continue; // 읽어드릴 자료를 가진 클라이언트 채널을 가져온다. SocketChannel client = (SocketChannel) key.channel(); // 어딘가에 할당된 버퍼에 클라이언트에서 읽은 자료를 저장한다. int bytesread = client.read(buffer); // Read()가 -1을 반환하면 스트림의 끝이라는 것을 나타내고 클라이언트가 // 접속해제되었음을 의미한다. 따라서 선택된 키를 등록해제하고 채널을 닫는다. if (bytesread == -1) { key.cancel(); client.close(); continue; } } } }2. 정규표현식
// 대소문자에 상관없이 "java"라는 모든 단어에 대해서 정확하게 표현된 // "Java"로 대체하는 String 메소드를 사용한다. s = s.replaceAll("(?i)\\bjava\\b", // 패턴: "java", 대소문자를 상관하지 않는다. "Java"); // 변경할 문자열 // java.util.regex 클래스의 패턴과 일치를 사용하는 보다 복잡한 정규표현식을 이용해보자 // "Java"로 시작하는 어떤 단어라도 기술할 수 있고 Java를 접두사로 갖는 어떠한 접미어도 // 캡쳐하는 패턴을 만든다. CASE_INSENTITIVE 플래그를 이용하므로 대소문자와 상관없이 매치된다. Pattern p = Pattern.compile("\\bJava(\\w*)", Pattern.CASE_INSENSITIVE); // 이 문장으로 패턴을 비교한다 String text = "Java is fun; JavaScript is funny."; // 텍스트 패턴을 비교할 Matcher 오브젝트를 생성한다. Matcher m = p.matcher(text); // 루프를 돌려서 텍스트 안의 모든 일치하는 패턴을 찾는다. while(m.find()) { // 각각의 일치에 대해서 패턴과 일치하는 텍스트와 문자열에서 위치를 출력한다. System.out.println("Found "" + m.group(0) + "" at position " + m.start(0)); // 또한 다른 접미사가 있다면 출력한다. if (m.start(1) < m.end(1)) System.out.println("Suffix is " + m.group(1)); }1. 표명(Assertion)
assert assertion ;혹은
assert assertion : errorcode ;표명 표현은 불린 표현이 되어야 한다는 사실을 기억해 두고 있어야 한다. 실제적인 의미는 비교 연산자나 불린 값을 갖는 메소드를 호출해야한다는 의미이다. errorcode 표현은 어떤 값이라도 가질 수 있다.
if (x == 0) { ... } else { assert x == 1 : x; // x는 0이거나 1이어야 한다. ... }비슷한 용례로는 switch 구문을 사용하는 것이 있다. default인 경우를 포함하지 않는 switch를 작성하는 것이 아니라면 가능한 한 모든 경우를 명확하게 열거하는 표명을 이용하여 모든 가정을 코딩할 수 있다. 예를 들면
switch(x) { case -1: return LESS; case 0: return EQUALS; case 1: return GREATER; default: assert false:x; // x가 -1, 0 혹은 1이 아니면 AssertionError로 넘긴다. }assert false;는 항상 실패한다는 것에 주목하자. 이런 형태의 구문은 여러분이 결코 도달할 수 없다고 믿는 "dead end" 구문에서 특히 유용하다.
java -ea:com.example.sorters.MergeSort // 하나의 클래스에 대해 표명을 활성화한다. java -ea:com.example.sorters... // 패키지에 대해 표명을 활성화한다.또한 -da 인자를 이용하여 클래스나 패키지에서 표명을 비활성화 할 수도 있다.
이전 글 : Doctype을 올바르게 사용하자
다음 글 : 에필로그 - J2SE의 미래, 자바의 앞날
최신 콘텐츠