package uk.co.mmscomputing.sms; import java.io.*; public class SMSNibbleInputStream extends FilterInputStream{ // [1] p.40 9.1.2.3 Semi-octet representation // 1010="*", 1011="#", 1100="a", 1101="b", 1110="c" private int nibble; private boolean haveNibble; public SMSNibbleInputStream(InputStream in){ super(in); nibble=0; haveNibble=false; } private int convert(int nibble){ nibble&=0x000F; if(nibble<=0x09){ return nibble+0x30; } switch(nibble){ case 10: return '*'; case 11: return '#'; case 12: return 'a'; case 13: return 'b'; case 14: return 'c'; } return -1; // 15: 0000 1111 filler nibble at end } public int read()throws IOException{ if(haveNibble){ haveNibble=false; return nibble; } int b=super.read(); if(b==-1){return -1;} nibble=convert(b>>4); haveNibble=true; return convert(b); } public int read(byte[] buf, int off, int len)throws IOException{ if(buf==null){ throw new NullPointerException(getClass().getName()+".read(byte[] buf, int off, int len): buf is null"); } if((off<0)||(len<0)||(buf.length<(off+len))){ throw new IndexOutOfBoundsException(getClass().getName()+".read(byte[] buf, int off, int len): index off ["+off+"] or len ["+len+"] out of bounds ["+buf.length+"]."); } int b; int count=0; while(count<len){ b=read(); if(b==-1){return (count==0)?-1:count;} buf[off++]=(byte)b; count++; } return count; } public static void main(String[] argv){ try{ byte[] bytes={(byte)0x70,(byte)0x59,(byte)0x57,(byte)0x20,(byte)0x12,(byte)0xF6}; InputStream src = new ByteArrayInputStream(bytes); SMSNibbleInputStream in = new SMSNibbleInputStream(src); /* int b=in.read(); while(b!=-1){ System.out.println("\n\t0x"+Integer.toHexString(b)+"\n\t"+Integer.toBinaryString(b)+"b\n\t"+((char)b)+"\n"); b=in.read(); } */ bytes=new byte[20]; int len=in.read(bytes); System.err.println("len = "+len); System.err.println(new String(bytes,0,len)); }catch(Exception e){ e.printStackTrace(); } } } // [1] ETSI TS 123 040 (2004-09) // [2] 3GPP TS 23.038 V7.0.0 (2006-03) // [3] GSM 44.008