Mam tablicę bajtów wypełnioną liczbami szesnastkowymi i drukowanie jej w prosty sposób jest dość bezcelowe, ponieważ istnieje wiele elementów, które nie mogą zostać wydrukowane. Potrzebuję dokładnego kodu szesnastkowego w postaci:3a5f771c
649
toHexString(...)
metodę, która może pomóc, jeśli tego właśnie szukasz.String.format(...)
Można także wykonać kilka sztuczek formatowania przy użyciu ciągu%2x
kodu.Odpowiedzi:
Z dyskusji tutaj , a zwłaszcza z tej odpowiedzi, jest to funkcja, z której obecnie korzystam:
Moje własne małe testy porównawcze (milion bajtów tysiąc razy, 256 bajtów 10 milionów razy) wykazały, że jest on znacznie szybszy niż jakakolwiek inna alternatywa, o połowę krótszy na długich tablicach. W porównaniu z odpowiedzią, z której zacząłem, przejście na operacje bitowe --- jak sugerowano w dyskusji --- skróciło około 20% czasu na długie tablice. (Edycja: Kiedy mówię, że jest szybszy niż alternatywy, mam na myśli alternatywny kod oferowany w dyskusjach. Wydajność jest równoważna kodekowi Commons, który używa bardzo podobnego kodu).
Wersja 2k20 w odniesieniu do kompaktowych ciągów Java 9:
źródło
String printHexBinary(byte[])
ibyte[] parseHexBinary(String)
.printHexBinary
jest jednak znacznie (2x) wolniejszy niż funkcja w tej odpowiedzi. (Sprawdziłem źródło; używa astringBuilder
.parseHexBinary
Używa tablicy). Naprawdę jednak, dla większości celów jest wystarczająco szybki i prawdopodobnie już go masz.printHexBinary
?javax.xml.bind.DataTypeConverter
jest usuwany z Java 11.Apache Commons Codec biblioteka ma Hex klasę dla robi tylko ten rodzaj pracy.
źródło
import org.apache.commons.codec.*;
mógłbyś zrobićimport org.apache.commons.codec.binary.Hex;
org.bouncycastle.util.encoders.Hex
przy użyciu tej metody:String toHexString(byte[] data)
Ta metoda
javax.xml.bind.DatatypeConverter.printHexBinary()
, będąca częścią architektury Java Binding XML (JAXB) , była wygodnym sposobem konwersjibyte[]
łańcucha szesnastkowego.DatatypeConverter
Klasa zawiera także wiele innych przydatnych metod manipulacji danymi.W Javie 8 i wcześniejszych JAXB był częścią standardowej biblioteki Java. Został on przestarzały w Javie 9 i usunięty w Javie 11 , w ramach próby przeniesienia wszystkich pakietów Java EE do ich własnych bibliotek. To długa historia . Teraz
javax.xml.bind
nie istnieje, a jeśli chcesz użyć JAXB, który zawieraDatatypeConverter
, musisz zainstalować JAXB API i JAXB Runtime z Maven.Przykładowe użycie:
Spowoduje to:
Ta odpowiedź jest taka sama jak ta .
źródło
Najprostsze rozwiązanie, brak zewnętrznych bibliotek lib, brak cyfr stałych:
źródło
Rozwiązanie Guava dla kompletności:
Teraz
hex
jest"48656c6c6f20776f726c64"
.źródło
new HashCode(bytes).toString()
.HashCode.fromBytes(checksum).toString()
Ten prosty oneliner działa dla mnie
String result = new BigInteger(1, inputBytes).toString(16);
EDYCJA - użycie tego spowoduje usunięcie zer wiodących, ale hej działał w moim przypadku użycia. Dzięki @Voicu za zwrócenie na to uwagi
źródło
Oto kilka typowych opcji uporządkowanych od prostych (jedno-liniowy) do złożonych (ogromna biblioteka). Jeśli jesteś zainteresowany wydajnością, zapoznaj się z mikro-testami poniżej.
Opcja 1: Fragment kodu - prosty
Jednym bardzo prostym rozwiązaniem jest użycie
BigInteger
reprezentacji szesnastkowej:Zauważ, że ponieważ obsługuje liczby, które nie są dowolnymi ciągami bajtów , pominie zera wiodące - może to być lub nie być to, czego chcesz (np.
000AE3
Vs0AE3
dla danych 3-bajtowych). Jest to również bardzo wolne, około 100 razy wolniejsze w porównaniu do następnej opcji.Opcja 2: fragment kodu - zaawansowane
Oto w pełni funkcjonalny, kopiowany i wklejany fragment kodu obsługujący wielkie / małe litery oraz endianness . Jest zoptymalizowany, aby zminimalizować złożoność pamięci i zmaksymalizować wydajność i powinien być kompatybilny ze wszystkimi nowoczesnymi wersjami Java (5+).
Pełny kod źródłowy z licencją i dekoderem Apache v2 można znaleźć tutaj .
Opcja 3: Korzystanie z małej zoptymalizowanej biblioteki: bytes-java
Pracując nad poprzednim projektem, stworzyłem ten mały zestaw narzędzi do pracy z bajtami w Javie. Nie ma zewnętrznych zależności i jest kompatybilny z Javą 7+. Obejmuje między innymi bardzo szybki i dobrze przetestowany dekoder / dekoder HEX:
Możesz to sprawdzić na Github: bytes-java .
Opcja 4: kodek Apache Commons
Oczywiście są dobre kodeki wspólne . ( opinia ostrzegawcza przed nami ) Podczas pracy nad projektem opisanym powyżej przeanalizowałem kod i byłem bardzo rozczarowany; wiele zduplikowanych niezorganizowanych kodów, przestarzałe i egzotyczne kodeki są prawdopodobnie przydatne tylko dla bardzo nielicznych i dość skomplikowanych i powolnych implementacji popularnych kodeków (szczególnie Base64). W związku z tym podjąłbym świadomą decyzję, jeśli chcesz skorzystać z niej lub z alternatywy. W każdym razie, jeśli nadal chcesz go używać, oto fragment kodu:
Opcja 5: Google Guava
Najczęściej masz Guava jako zależność. Jeśli tak, użyj:
Opcja 6: Spring Security
Jeśli korzystasz ze struktury Spring z Spring Security , możesz użyć następujących opcji:
Opcja 7: dmuchany zamek
Jeśli korzystasz już z ram bezpieczeństwa Bouncy Castle , możesz użyć jego wykorzystania
Hex
:Niezupełnie opcja 8: Zgodność z Java 9+ lub „Nie używaj JAXBs javax / xml / bind / DatatypeConverter”
W poprzednich wersjach Java (8 i niższych) kod Java dla JAXB był dołączany jako zależność środowiska wykonawczego. Od modularyzacji Java 9 i Jigsaw Twój kod nie może uzyskać dostępu do innego kodu poza modułem bez wyraźnej deklaracji. Więc pamiętaj, jeśli otrzymasz wyjątek, taki jak:
podczas pracy na JVM z Javą 9+. Jeśli tak, przełącz implementacje na dowolne z powyższych rozwiązań. Zobacz także to pytanie .
Mikroskopy
Oto wyniki z prostego macierzy bajtowej JMH do mikro-testów o różnych rozmiarach . Wartości są operacjami na sekundę, więc im wyższa, tym lepiej. Zauważ, że mikroskopy bardzo często nie reprezentują zachowania w świecie rzeczywistym, więc weź te wyniki z odrobiną soli.
Specyfikacja: JDK 8u202, i7-7700K, Win10, 24 GB RAM. Zobacz pełny test tutaj .
źródło
Użyj klasy DataTypeConverter
javax.xml.bind.DataTypeConverter
String hexString = DatatypeConverter.printHexBinary(bytes[] raw);
źródło
Użyłbym czegoś takiego dla stałej długości, np. Skrótów:
źródło
Znalazłem tutaj trzy różne sposoby: http://www.rgagnon.com/javadetails/java-0596.html
Najbardziej elegancki, jak zauważa, myślę, że jest ten:
źródło
if (raw == null) return null
nie zawiedzie szybko. Dlaczego miałbyś kiedykolwiek używaćnull
klucza?Przy niewielkich kosztach przechowywania tabeli odnośników ta implementacja jest prosta i bardzo szybka.
źródło
BYTE2HEX
tablicy za pomocą prostegofor
cyklu?static { }
bloku.Co powiesz na to?
źródło
Nie musimy używać żadnej zewnętrznej biblioteki ani pisać kodu na podstawie pętli i stałych.
Wystarczy tylko to:
źródło
Wolę użyć tego:
Jest to nieco bardziej elastyczne dostosowanie przyjętej odpowiedzi. Osobiście zachowuję zarówno akceptowaną odpowiedź, jak i to przeciążenie wraz z nią, do użytku w większej liczbie kontekstów.
źródło
Zwykle używam następującej metody do instrukcji debuf, ale nie wiem, czy jest to najlepszy sposób, czy nie
źródło
StringBuilder buf = new StringBuilder(data.length * 2);
.Ok, więc istnieje wiele sposobów, aby to zrobić, ale jeśli zdecydujesz się użyć biblioteki, radzę zajrzeć do twojego projektu, aby sprawdzić, czy coś zostało zaimplementowane w bibliotece, która jest już częścią twojego projektu przed dodaniem nowej biblioteki po prostu to zrobić. Na przykład, jeśli jeszcze tego nie masz
może masz ...
źródło
Jeśli korzystasz ze środowiska Spring Security, możesz użyć:
źródło
Dodanie słoika narzędziowego dla prostej funkcji nie jest dobrą opcją. Zamiast tego montuj własne klasy narzędzi. możliwe jest szybsze wdrożenie.
źródło
Mały wariant rozwiązania zaproponowanego przez @maybewecouldstealavan, który pozwala wizualnie łączyć N bajtów razem w wyjściowym ciągu szesnastkowym:
To jest:
źródło
Nie mogę znaleźć na tej stronie żadnego rozwiązania, które by tego nie zrobiło
Oto rozwiązanie, które nie ma wad powyżej (żadne moje obietnice nie mają innych wad)
Nie udało mi się uzyskać tego pod 62 kodami, ale jeśli możesz żyć bez zerowania w przypadku, gdy pierwszy bajt jest mniejszy niż 0x10, poniższe rozwiązanie używa tylko 23 kodów. Naprawdę pokazuje, jak rozwiązania „łatwe do samodzielnego wdrożenia”, takie jak „pad z zerem, jeśli długość łańcucha jest nieparzysta”, mogą stać się dość drogie, jeśli natywna implementacja nie jest już dostępna (lub w tym przypadku, jeśli BigInteger miał opcję prefiksu zerami w toString).
źródło
Moje rozwiązanie jest oparte na rozwiązaniu możeWeCouldStealAVan, ale nie opiera się na żadnych dodatkowych tabelach wyszukiwania. Nie używa hacków typu int-to-char (w rzeczywistości
Character.forDigit()
robi to, porównując, aby sprawdzić, czym naprawdę jest cyfra), a zatem może być nieco wolniejszy. Możesz go używać gdziekolwiek chcesz. Twoje zdrowie.źródło
// Przesunięcie bajtów jest bardziej wydajne // Możesz także użyć tego
źródło
Jeśli szukasz tablicy bajtów dokładnie takiej jak dla Pythona, przekonwertowałem tę implementację Java na python.
źródło
źródło
Oto
java.util.Base64
implementacja przypominająca (częściowa), prawda?źródło
źródło
źródło