HexConverter.java

download

// Mała klasa pisana dla projektu ActiveDocument podczas pracy w DNet.
// Jej zadaniem było dokonywać konwersji z zapisu HEX (dwa znaki na bajt)
// do formatu binarnego. Lokalna aplikacja pisana w C++ działająca na
// komputerze klienta służyła do podpisywania plików
// binarnych/sprawdzania podpisów i wysyłała do aplikacji na serwerze
// pliki podpisów wraz z dodatkowymi danymi.
// 
// Aby zapewnić przenośność przygotowałem prosty format tekstowy, w
// którym przy pomocy zapisu HEX przenosiłem pliki binarne pomiędzy
// klientem (C++) a serwerem (Java).
// 
// Proszę zwrócić uwagę na metodę selfTest(), która sprawdza poprawność
// klasy i służy jako dokumentacja użycia klasy.
//
// Dariusz Cieślak, cieslakd at gazeta.pl

package activeDocument;

import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.BufferedOutputStream;

public class HexConverter
{
    String m_sHexBody;

    public HexConverter(String sHexBody)
    {
        m_sHexBody = sHexBody;
    }

    private static int  hexToByte(char ch) throws Exception
    {
        final int nBASE = 16;
        int n = Character.digit(ch, nBASE);

        if(n == -1)
            throw new Exception("bad hex digit: '" + ch + "'");

        return n;
    }

    /** zapisuje podanyc w kontruktorze ciąg HEX do formatu
        binarnego */
    public void saveBinary(String sOutputFile) throws Exception
    {
        BufferedOutputStream bos =
            new BufferedOutputStream(
                new FileOutputStream(sOutputFile));

        // one byte written as two hex digits
        int nChars = m_sHexBody.length();

        // length should be even
        should((nChars & 1) == 0, "Length should be even:" + nChars);

        int nChar = 0;
        while(nChar < nChars)
        {
            bos.write(
                _hexToByte(m_sHexBody.charAt(nChar)) * 16 +
                _hexToByte(m_sHexBody.charAt(nChar + 1)));
            nChar += 2;
        }

        bos.close();
    }


    public static void selfTest() throws Exception
    {
        should(_hexToByte('f') == 0xf);
        should(_hexToByte('0') == 0x0);
        should(_hexToByte('a') == 0xa);

        final String sFILE = "c:/temp/c.txt";

        HexConverter hc = new HexConverter("12fc6f");

        hc.saveBinary(sFILE);

        BufferedInputStream bis = new BufferedInputStream(
                new FileInputStream(sFILE));

        should(bis.read() == 0x12);
        should(bis.read() == 0xfc);
        should(bis.read() == 0x6f);
        should(bis.read() == -1);

        bis.close();
    }

    /** raises error when condition isn't true */
    static void should(boolean boCond,String sText) throws Exception
    {
        if(!boCond)
            throw new Exception(sText);
    }

    /** raises error when condition isn't true */
    static void should(boolean boCond) throws Exception
    {
        if(!boCond)
            throw new Exception();
    }
}

(...) Nie ma bowiem łatwych odpowiedzi. Nie istnieje nic takiego jak najlepsze rozwiązanie - zarówno jeśli chodzi o narzędzia, jak i języki czy systemy operacyjne. Są jedynie systemy, które mogą być bardziej odpowiednie w konkretnych okolicznościach.

I tu właśnie do gry wchodzi pragmatyzm. Nie należy przywiązywać się do żadnej określonej metody, ale mieć na tyle rozległą wiedzę i doświadczenie, by w danej sytuacji wybrać dobre rozwiązanie. (...)

Andrew Hunt, David Thomas "Pragmatyczny Programista"