Skip to content

Commit c5a2fac

Browse files
committed
Java Base64 Encoder and Decoder
0 parents  commit c5a2fac

File tree

8 files changed

+469
-0
lines changed

8 files changed

+469
-0
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/.idea
2+
/.idea/*
3+
/target/*
4+
!/target/*.jar
5+
*.iml
6+

pom.xml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>ru.Antony</groupId>
8+
<artifactId>MIME_Decoder</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
<packaging>jar</packaging>
11+
<name>MIME_Decoder</name>
12+
13+
<build>
14+
<plugins>
15+
<plugin>
16+
<groupId>org.apache.maven.plugins</groupId>
17+
<artifactId>maven-jar-plugin</artifactId>
18+
<version>2.4</version>
19+
<configuration>
20+
<archive>
21+
<manifest>
22+
<mainClass>Frame</mainClass>
23+
</manifest>
24+
</archive>
25+
</configuration>
26+
</plugin>
27+
</plugins>
28+
</build>
29+
</project>

readme.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
��������� ��������� ����������/������������ ��������� ���� �/�� MIME (Base64)
2+
��������� ������������ ���������� ���� � ����� ��������, ������ �� ������� ��������� ������� ����. ��� ������� �� ������ ��������� �������� ��������� ���� �
3+
��������� �������������� ���� � ����� ����� � ����������� *.base64.
4+
5+
��� ������� �� ������ ������, ��������� ���������� ��������� ���� � ��������� ������� � ����� �����, ��� ���� �������� ��������� � ����� ����� � ����������� *_base64.dec
6+
����� ��������� ��������� ��������� ������������� - ���������� ������� ��� �������� �����, �.�. ������� ��� ����� ����� ��� � ����� ������. (�������� � Notepad++)

src/main/java/Base64.java

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import java.util.ArrayList;
2+
3+
public class Base64 {
4+
5+
private static int buffer; //здесь я храню символы и разбиваю блоки по 6 бит
6+
private static int BufferBitCounter = 0; // счетчик бит в буффере
7+
private static int numOfBits = 0; // число бит в строке которая передается на кодирование.
8+
public static ArrayList<Byte> ListOfBytes = new ArrayList<>();
9+
10+
// Это алфавит Base64;
11+
private final static String abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
12+
13+
14+
public static String StartEncode(byte[] inputArray) {
15+
String result = "";
16+
17+
// число бит, которое занимает кодируемое сообщение
18+
numOfBits = inputArray.length * 8;
19+
20+
// число бит должно быть кратным 6 (так как сообщение разбиваем на 6 бит)
21+
if (numOfBits % 6 == 0)
22+
result += Base64Encode(inputArray);
23+
else if (numOfBits % 6 == 2) {
24+
result += Base64Encode(inputArray) + "==";
25+
}
26+
27+
else if (numOfBits % 6 == 4) {
28+
result += Base64Encode(inputArray) + "=";
29+
}
30+
31+
return result;
32+
}
33+
34+
private static String Base64Encode(byte[] byteArr) {
35+
36+
buffer = 0;
37+
BufferBitCounter = 0;
38+
39+
String result = ""; // здесь будем хранить результат
40+
int temp6Bit = 0; // Временная переменная - в ней сохраняем 6-бит из буфера, путем смещения вправо
41+
42+
for (int i = 0; i < byteArr.length; ++i) {
43+
//for (byte symbol : byteArr) {
44+
byte symbol = byteArr[i];
45+
46+
/* т.к. в Java перменная byte знаковая и ее диапазон -127 ... 127
47+
будем использовать переменную short. В Java байты могут быть отрицат. величины,
48+
поэтому приводим их в нормальное значение добавив 256. */
49+
50+
short symbl = symbol;
51+
if (symbl < 0 ) symbl += 256;
52+
53+
buffer = (buffer << 8); // сдвигаем влево для добавления битов символа - 8 бит
54+
// (каждый новый символ занимает 8 бит)
55+
buffer = (buffer | symbl); // добавляем символ в буфер
56+
BufferBitCounter += 8; // Прибавляем счетчик бит в буффере на 8 бит (добавили символ - он занимает 8 бит)
57+
58+
/* Если количество бит в передаваеваемом сообщнии не кратно 6-ти (мы кодируем сообщение по 6 бит)
59+
тогда нам нужно добавить в самый конец цепочки байтов
60+
(поэтому мы здесь проверяем что i == byteArr.length -1)
61+
необходимые пустые биты, чтобы длина была кратной 6-ти
62+
*/
63+
if (i == byteArr.length -1 && numOfBits % 6 == 2) {
64+
buffer = buffer << 4;
65+
BufferBitCounter += 4;}
66+
else if (i == byteArr.length -1 && numOfBits % 6 == 4 ) {
67+
buffer = buffer << 2;
68+
BufferBitCounter += 2;}
69+
70+
// если наш счетчик в буфере больше или равен 6 - разбиваем буфер на блок из 6 бит
71+
while (BufferBitCounter >= 6)
72+
{
73+
/* получаем блок из 6-ти бит сдвигая вправо (Насколько нужно сдвинуть? Мы это определяем с помощью счетчика бит
74+
* мы сдвигаем столько бит, сколько показывает счетчик BufferBitCounter МИНУС 6,
75+
* т.к. 6 бит мы оставляем для блока в 6 бит, который мы кодируем в символ MIME64 */
76+
temp6Bit = buffer >> (BufferBitCounter - 6);
77+
BufferBitCounter -= 6; // После того как мы получили блок из 6 бит для MIME64 у нас буфер на 6 бит меньше
78+
79+
// Очищаем буффер, если счетчик использованных бит равен нулю
80+
if (BufferBitCounter == 0) {
81+
buffer = 0;
82+
}
83+
else {
84+
// очищаем буфер от выброшенных битов -- буфер имеет тип int - 32 бит
85+
buffer = (int) (buffer << (32 - BufferBitCounter));
86+
buffer = (int) (buffer >>> (32 - BufferBitCounter));
87+
}
88+
89+
result += abc.charAt(temp6Bit); // присваиваем с результату закодированный в MIME64 символ
90+
}
91+
}
92+
93+
return result; // Выводим закодированный в MIME64 символ на экран
94+
}
95+
96+
97+
public static byte[] StartDecode(byte[] bytes) {
98+
99+
// Вначале работы методов startMimeEncode и startMimeDecode инициализируем переменные нулями
100+
buffer = 0; // здесь я храню символы и разбиваю блоки по 6 бит
101+
BufferBitCounter = 0; // счетчик бит в буффере
102+
ListOfBytes.clear();
103+
104+
byte mimeAbcPosition; // Нам необходимо определить позицию символа в MIME-Алфавите
105+
char mimeLetter;
106+
107+
108+
// Перебираем поисмвольно тест закодированный в MIME64. Напомню, мы его перевели в массив байт, для удобства
109+
for (int i = 0; i < bytes.length; i++)
110+
{
111+
// Нам нужно теперь байт из массива перевести в символ (char)
112+
mimeLetter = (char)(bytes[i]);
113+
if (mimeLetter == '=' ) break;
114+
// и определить позицию символа в массиве алфавите MIME64
115+
mimeAbcPosition = (byte)abc.indexOf(mimeLetter);
116+
// теперь вызываем метод декодирования MIME64 отправляя туда позицию символа в алфавите MIME64
117+
Mime64Decode(mimeAbcPosition);
118+
}
119+
120+
Byte[] byteArray = new Byte[1];
121+
byteArray = ListOfBytes.toArray(byteArray);
122+
byte[] result = new byte[byteArray.length];
123+
for (int i = 0; i < byteArray.length; i++)
124+
result[i] = byteArray[i];
125+
126+
return result;
127+
}
128+
129+
/*
130+
* Метод принимает параметр - byte Symbol, который определяет положение символа в массиве-алфавите MIME64
131+
* В процессе работы метода - в буфере накапливаются биты
132+
*/
133+
public static void Mime64Decode(byte Symbol)
134+
{
135+
byte temp8bit = 0; // Временная переменная, для вырезания из буфера блоков по 8 бит (привычные нам символы в кодировке win-1251 занимают 8 бит)
136+
137+
/* Сдвигаем буфер влево на 6 бит для добавления битов нового числа-позиции в алфавите
138+
* (каждый новый символ (т.е. позиция в алфавите MIME) занимает 6 бит) */
139+
buffer = (buffer << 6);
140+
buffer = (buffer | Symbol); // добавляем новые биты в буфер в освобожденное место (сдвинули выше, освободив для битов место)
141+
BufferBitCounter += 6; // Теперь счетчик битов на 6 битов больше
142+
143+
// В случае если счетчик битов >= 8 разбиваем буфер на блоки из 8 битов
144+
while (BufferBitCounter >= 8)
145+
{
146+
/* получаем блок из 8-ти бит сдвигая вправо (Насколько нужно сдвинуть? Мы это определяем с помощью счетчика бит
147+
* мы сдвигаем столько бит, сколько показывает счетчик BufferBitCounter МИНУС 8,
148+
* т.к. 8 бит мы оставляем для блока в 8 бит, который мы декодируем в символ windows-1251 */
149+
temp8bit = (byte)(buffer >> (BufferBitCounter - 8));
150+
BufferBitCounter -= 8; // Теперь счетчик битов в буфере уменьшается на 8
151+
buffer = (buffer << (16 - BufferBitCounter)); // очищаем буфер от выброшенных битов -- буфер имеет тип ushort - 16 бит
152+
buffer = (buffer >> (16 - BufferBitCounter));
153+
154+
// добавляем декодированные 8битные кусочки в "массив" байтов (List<byte>), который затем будет преобразован в текст в формате UTF-8
155+
ListOfBytes.add(temp8bit);
156+
}
157+
}
158+
159+
}

src/main/java/FileUtils.java

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import java.io.*;
2+
import java.util.Scanner;
3+
4+
public class FileUtils {
5+
6+
// расширение для закодированного файла
7+
private static final String encodeFileExtention = ".base64";
8+
private static final String decodeFileExtention = "_base64.dec";
9+
private static final int cols = 76; // количество символов в строке, при записи файла,
10+
// после которых ставить перенос на новую строку, для удобства чтения
11+
12+
13+
public static void writeEncoded(File filename, String strOut) throws FileNotFoundException {
14+
15+
filename = getFileNameForEncoded(filename);
16+
17+
try (PrintWriter out = new PrintWriter(filename)) {
18+
19+
int i = 0;
20+
for (char c : strOut.toCharArray()) {
21+
i++;
22+
out.print(c);
23+
if (i % cols == 0) out.println();
24+
}
25+
}
26+
}
27+
28+
public static void writeDecoded(File filename, byte[] bytes) throws IOException {
29+
30+
filename = getFileNameForDecoded(filename);
31+
32+
try (DataOutputStream out = new DataOutputStream(new FileOutputStream(filename))) {
33+
out.write(bytes);
34+
out.flush();
35+
}
36+
}
37+
38+
public static byte[] readSelectedFile(File fileName) throws IOException {
39+
40+
byte[] byteArr;
41+
42+
String ReadIn = "";
43+
try (Scanner in = new Scanner(new FileInputStream(fileName))) {
44+
45+
while (in.hasNext()) {
46+
ReadIn += in.nextLine();
47+
}
48+
}
49+
50+
byteArr = ReadIn.getBytes();
51+
52+
/*
53+
try (DataInputStream in = new DataInputStream(new FileInputStream(fileName))) {
54+
byteArr = new byte[in.available()];
55+
in.readFully(byteArr);
56+
} */
57+
58+
return byteArr;
59+
60+
}
61+
62+
63+
private static String removeUTF8BOM(String s) {
64+
if (s.startsWith("\uFEFF")) {
65+
s = s.substring(1);
66+
}
67+
return s;
68+
}
69+
70+
71+
/* В этом методе заменяется расширение выбранного файла, на заданное в константе
72+
класса FileUtils.encodeFileExtention (.base64) */
73+
private static File getFileNameForEncoded(File file) {
74+
// здесь вычисляем путь к файлу (диск:\путь до файла\
75+
String path = file.toString().substring(0, file.toString().lastIndexOf("\\") + 1);
76+
// здесь вычисляем имя файла (без расширения)
77+
String fileName = file.toString().substring(file.toString().lastIndexOf("\\") + 1,
78+
file.toString().indexOf("."));
79+
// формируем новое имя файла, изменив расширение
80+
File fileToWrite = new File(path + fileName + encodeFileExtention);
81+
82+
83+
return fileToWrite;
84+
}
85+
86+
/* В этом методе заменяется расширение выбранного файла, на заданное в константе
87+
класса FileUtils.encodeFileExtention (*_base64.dec) */
88+
private static File getFileNameForDecoded(File file) {
89+
// здесь вычисляем путь к файлу (диск:\путь до файла\
90+
String path = file.toString().substring(0, file.toString().lastIndexOf("\\") + 1);
91+
// здесь вычисляем имя файла (без расширения)
92+
String fileName = file.toString().substring(file.toString().lastIndexOf("\\") + 1,
93+
file.toString().indexOf("."));
94+
// формируем новое имя файла, изменив расширение
95+
File fileToWrite = new File(path + fileName + decodeFileExtention);
96+
97+
98+
return fileToWrite;
99+
}
100+
101+
}

0 commit comments

Comments
 (0)