This commit is contained in:
Ivan I. Ovchinnikov 2023-01-12 23:21:17 +03:00
parent 3e095d010d
commit c662ae1464
3 changed files with 158 additions and 49 deletions

View File

@ -700,9 +700,9 @@ cat0 equal to cat3? false
\subsection*{Практическое задание} \subsection*{Практическое задание}
\begin{enumerate} \begin{enumerate}
\item создать пару-тройку текстовых файлов. Для упрощения (не разбираться с кодировками) внутри файлов следует писать текст только латинскими буквами. \item Cоздать пару-тройку текстовых файлов. Для упрощения (чтобы не разбираться с кодировками) внутри файлов следует писать текст только латинскими буквами.
\item написать метод, осуществляющий конкатенацию переданных ей в качестве параметров файлов (не особо важно, в первый допишется второй или во второй первый, или файлы вовсе объединятся в какой-то третий); \item Написать метод, осуществляющий конкатенацию (объединение) переданных ей в качестве параметров файлов (не важно, в первый допишется второй или во второй первый, или файлы вовсе объединятся в какой-то третий);
\item написать метод поиска слова внутри файла. \item Написать метод поиска слова внутри файла.
\end{enumerate} \end{enumerate}
\newpage \newpage

BIN
seminars/build/jtc5-05c.pdf Normal file

Binary file not shown.

View File

@ -2,7 +2,7 @@
\usepackage{spreadtab} \usepackage{spreadtab}
\begin{document} \begin{document}
\setcounter{section}{3} \setcounter{section}{4}
\section{Семинар: обработка исключений} \section{Семинар: обработка исключений}
\subsection{Инструментарий} \subsection{Инструментарий}
\begin{itemize} \begin{itemize}
@ -73,30 +73,30 @@
\end{itemize} \end{itemize}
\item \textbf{Вопросы и ответы:} \item \textbf{Вопросы и ответы:}
\begin{enumerate} \begin{enumerate}
\item Перечисление -- это: 2 \item Что такое GPT?
\begin{enumerate} \begin{enumerate}
\item массив \item General partition trace;
\item класс \item GUID partition table;
\item объект \item Greater pass timing.
\end{enumerate} \end{enumerate}
\item Инкапсуляция с использованием внутренних классов: 2 \item Строки в языке Java -- это:
\begin{enumerate} \begin{enumerate}
\item остаётся неизменной \item классы;
\item увеличивается \item массивы;
\item уменьшается \item объекты.
\end{enumerate}
\item Ссылка на местонахождение -- это:
\begin{enumerate}
\item URI;
\item URL;
\item URN.
\end{enumerate}
\item Возможно ли чтение совершенно случайного байта данных из потока, к которому подключен объект \code{BufferedInputStream}?
\begin{enumerate}
\item да;
\item нет;
\item да, если это поток в программу из локального файла.
\end{enumerate} \end{enumerate}
\item Обработчик исключений -- это объект, работающий 1
\begin{enumerate}
\item в специальном потоке
\item в специальном ресурсе
\item в специальный момент
\end{enumerate}
\item Стектрейс - это 2
\begin{enumerate}
\item часть потока выполнения программы;
\item часть объекта исключения;
\item часть информации в окне отладчика.
\end{enumerate}
\end{enumerate} \end{enumerate}
\end{itemize} \end{itemize}
@ -110,41 +110,150 @@
\item возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов. \item возможно, по предварительному опросу, демонстрирует и разбирает вариант решения одного из студентов.
\end{itemize} \end{itemize}
\item \textbf{Домашнее задание из лекции:} \item \textbf{Домашнее задание из лекции:}
\begin{itemize} \begin{itemize}
\item Напишите два наследника класса \code{Exception}: ошибка преобразования строки и ошибка преобразования столбца. \item Создать пару-тройку текстовых файлов. Для упрощения (чтобы не разбираться с кодировками) внутри файлов следует писать текст только латинскими буквами.
\textbf{Вариант решения} \textbf{Вариант решения}
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Простые наследники}] Задание не предполагало кода, но будет плюсом, если студенты создали файлы не вручную, а программным кодом. Для этого и последующих заданий понадобится набор констант и вспомогательный массив с названиями файлов
private static final class ColumnMismatchException extends RuntimeException { \begin{lstlisting}[language=Java,style=JCodeStyle,label={},caption={}]
ColumnMismatchException(String message) { private static final Random rnd = new Random();
super("Columns exception: " + message); private static final int CHAR_BOUND_L = 65;
} private static final int CHAR_BOUND_H = 90;
private static final int FILES_AMOUNT = 10;
private static final int WORDS_AMOUNT = 5;
private static final int WORD_LENGTH = 10;
private static final String WORD_TO_SEARCH = "geekbrains";
String[] fileNames = new String[FILES_AMOUNT];
for (int i = 0; i < fileNames.length; i++)
fileNames[i] = "file_" + i + ".txt";
\end{lstlisting}
Файл записывается простым выходным потоком, в который (в приведённом ниже примере) записывается строка, сгенерированная методом. Из строки выделяется массив байтов методом \code{getBytes()}.
\begin{lstlisting}[language=Java,style=JCodeStyle,label={},caption={}]
private static String generateSymbols(int amount) {
StringBuilder sequence = new StringBuilder();
for (int i = 0; i < amount; i++)
sequence.append((char) (CHAR_BOUND_L + rnd.nextInt(CHAR_BOUND_H - CHAR_BOUND_L)));
return sequence.toString();
} }
private static final class NumberIsNotNumberException extends RuntimeException { private static void writeFileContents(String fileName, int length) throws IOException {
NumberIsNotNumberException(String message) { FileOutputStream fos = new FileOutputStream(fileName);
super("Not a number found: " + message); fos.write(generateSymbols(length).getBytes());
} fos.flush();
fos.close();
} }
\end{lstlisting} \end{lstlisting}
\item Разработайте исключения-наследники так, чтобы они информировали пользователя в формате ожидание/реальность.
\begin{lstlisting}[language=Java,style=JCodeStyle,caption={Составное сообщение}] Вызов методов обёрнут в \code{try...catch} и формирует сразу файлы как для второго задания (конкатенации), так и третьего (поиска).
private static final class RowMismatchException extends RuntimeException { \begin{lstlisting}[language=Java,style=JCodeStyle,label={},caption={}]
RowMismatchException(int expected, int current, String value) { try {
super(String.format("Rows exception: expected %d rows. Received %d rows in '%s' string", //#1
expected, current, value)); for (int i = 0; i < fileNames.length; i++)
} if (i < 2)
writeFileContents(fileNames[i], 100);
else
writeFileContents(fileNames[i], WORDS_AMOUNT, WORD_LENGTH);
System.out.println("First task results are in file_0 and file_1.");
} }
\end{lstlisting} catch (Exception ex) { throw new RuntimeException(ex); }
\end{lstlisting}
\item для проверки напишите программу, преобразующую квадратный массив целых чисел 5х5 в сумму чисел в этом массиве, при этом, программа должна выбросить исключение, если строк или столбцов в исходном массиве окажется не 5.
\textbf{Вариант решения представлен в приложении \ref{appendix:hw3}} \item Написать метод, осуществляющий конкатенацию (соединение) переданных ей в качестве параметров файлов (не особенно важно, в первый допишется второй или во второй первый, или файлы вовсе объединятся в какой-то третий);
\end{itemize} \textbf{Вариант решения}
Метод конкатенации моет также быть написан множеством способов, но важно, чтобы при буферизации (чаще всего решения содержат именно буферизованные варианты) не терялись символы, например, пробелы или переходы на новую строку. Также часто встречается дополнительная буферизация внутри программы, например, в строку, при помощи \code{StringBuilder}, что будет являться грубой ошибкой при конкатенации больших или бинарных файлов. Поэтому ниже представлен вариант решения с посимвольным чтением и записью в результирующий файл.
\begin{lstlisting}[language=Java,style=JCodeStyle,label={},caption={}]
private static void concatenate(String file_in1, String file_in2, String file_out) throws IOException {
FileOutputStream fos = new FileOutputStream(file_out);
int ch;
FileInputStream fis = new FileInputStream(file_in1);
while ((ch = fis.read()) != -1)
fos.write(ch);
fis.close();
fis = new FileInputStream(file_in2);
while ((ch = fis.read()) != -1)
fos.write(ch);
fis.close();
fos.flush();
fos.close();
}
\end{lstlisting}
Вызов метода можно записать в секцию \code{try...catch} предыдущего задания или написать новую.
\begin{lstlisting}[language=Java,style=JCodeStyle,label={},caption={}]
try {
//#2
concatenate(fileNames[0], fileNames[1], "FILE_OUT.txt");
System.out.println("Second task result is in FILE_OUT.");
}
catch (Exception ex) { throw new RuntimeException(ex); }
\end{lstlisting}
\item Написать метод поиска слова внутри файла.
\textbf{Вариант решения}
Для поиска слова понадобится файл не со сплошными символами (хотя и в таком алгоритм поиска должен отработать нормально), а со словами, разделёнными пробелами. Для этого можно видоизменить метод генерации файла и написать перегруженный, который будет по некоторому псевдослучайному условию вставлять в файл через пробел либо случайно сгенерированную последовательность символов, либо слово, заранее определённое, как искомое.
\begin{lstlisting}[language=Java,style=JCodeStyle,label={},caption={}]
private static void writeFileContents(String fileName, int words, int length) throws IOException {
FileOutputStream fos = new FileOutputStream(fileName);
for (int i = 0; i < words; i++) {
if(rnd.nextInt(WORDS_AMOUNT) == WORDS_AMOUNT / 2)
fos.write(WORD_TO_SEARCH.getBytes());
else
fos.write(generateSymbols(length).getBytes());
fos.write(' ');
}
fos.flush();
fos.close();
}
\end{lstlisting}
Формально, можно выполнить работу следующим образом, используя \code{Scanner}, сравнивая слова «от пробела до пробела»
\begin{lstlisting}[language=Java,style=JCodeStyle,label={},caption={}]
private static boolean fileScanner(String fileName, String word) throws IOException {
Scanner sc = new Scanner(new FileInputStream(fileName));
word = word.toLowerCase(); // \n
while (sc.hasNext()) {
String line = sc.nextLine();
line = line.toLowerCase();
if (line.contains(word)) return true;
}
return false;
}
\end{lstlisting}
Но более гибким получится алгоритм, ищущий непосредственно последовательность символов, сравнивая их по одному, это позволяет искать не только словосочетания, но и, например, диалоги персонажей в книге.
\begin{lstlisting}[language=Java,style=JCodeStyle,label={},caption={}]
private static boolean isInFile(String fileName, String search) throws IOException {
FileInputStream fis = new FileInputStream(fileName);
byte[] searchSequence = search.getBytes();
int ch;
int i = 0; // geekgeekbrains
while ((ch = fis.read()) != -1) {
if (ch == searchSequence[i])
i++;
else {
i = 0;
if (ch == searchSequence[i]) i++;
}
if (i == searchSequence.length) {
fis.close();
return true;
}
}
fis.close();
return false;
}
\end{lstlisting}
\end{itemize}
\end{itemize} \end{itemize}
\subsubsection{Вопросы и ответы} \subsubsection{Вопросы и ответы}