-
Notifications
You must be signed in to change notification settings - Fork 0
FTP #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
FTP #9
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| plugins { | ||
| id 'java-library' | ||
| } | ||
|
|
||
| dependencies { | ||
| api 'org.apache.commons:commons-math3:3.6.1' | ||
|
|
||
| implementation 'com.google.guava:guava:23.0' | ||
|
|
||
| compile group: 'org.jetbrains', name: 'annotations', version: '15.0' | ||
| compile group: 'commons-io', name: 'commons-io', version: '2.6' | ||
|
|
||
| testCompile group: 'org.hamcrest', name: 'hamcrest-all', version: '1.3' | ||
| testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.1.0' | ||
| testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '5.0.0-M4' | ||
|
|
||
| testImplementation 'junit:junit:4.12' | ||
| } | ||
|
|
||
| repositories { | ||
| jcenter() | ||
| } | ||
| task wrapper(type: Wrapper) { | ||
| description = 'Generates gradlew[.bat] scripts' | ||
| gradleVersion = '4.6' | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| #Sun Apr 22 23:21:38 MSK 2018 | ||
| distributionBase=GRADLE_USER_HOME | ||
| distributionPath=wrapper/dists | ||
| zipStoreBase=GRADLE_USER_HOME | ||
| zipStorePath=wrapper/dists | ||
| distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| rootProject.name = 'FTP' | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| import org.apache.commons.io.IOUtils; | ||
| import org.jetbrains.annotations.NotNull; | ||
|
|
||
| import java.io.*; | ||
| import java.net.Socket; | ||
| import java.nio.file.FileAlreadyExistsException; | ||
|
|
||
| /** | ||
| * This class provides methods to work with FTPServer. These are: | ||
| * | ||
| * {@link FTPClient#list(String)} -- prints all files in the target directory. | ||
| * | ||
| * {@link FTPClient#get(String, String)} -- downloads and saves file from the | ||
| * server to the target file. | ||
| */ | ||
| @SuppressWarnings({"unused", "WeakerAccess"}) | ||
| public class FTPClient { | ||
|
|
||
| private final static int BUF_SIZE = 2048; | ||
|
|
||
| @NotNull | ||
| final private DataOutputStream os; | ||
| @NotNull | ||
| final private DataInputStream is; | ||
|
|
||
| /** | ||
| * Creates new client, that connected to the FTPServer. | ||
| * | ||
| * @param url servers url. | ||
| * @param port port to connect. | ||
| * @throws IOException if any IOException occurred. | ||
| */ | ||
| public FTPClient(final String url, final int port) throws IOException { | ||
| final Socket socket = new Socket(url, port); | ||
| os = new DataOutputStream(socket.getOutputStream()); | ||
| is = new DataInputStream(socket.getInputStream()); | ||
| } | ||
|
|
||
| /** | ||
| * Creates new client, that connected to the FTPServer. | ||
| * | ||
| * @param url servers url. | ||
| * @throws IOException if any IOException occurred. | ||
| */ | ||
| public FTPClient(final String url) throws IOException { | ||
| this(url, FTPServer.DEFAULT_PORT); | ||
| } | ||
|
|
||
| /** | ||
| * Prints list of all files (including folders), inside the source folder. | ||
| * | ||
| * Also for every file prints whether the file is a directory or not. | ||
| * | ||
| * @param source target folder. | ||
| * @throws IOException if any IOException occurred. | ||
| */ | ||
| public void list(@NotNull final String source) throws IOException { | ||
| os.writeInt(1); | ||
| os.writeUTF(source); | ||
| os.flush(); | ||
|
|
||
| final int number = is.readInt(); | ||
| System.out.println("Total number of files: " + number); | ||
| for (int i = 0; i < number; i++) { | ||
| final String name = is.readUTF(); | ||
| final boolean isFolder = is.readBoolean(); | ||
| final String isFolderString = isFolder ? "is a folder." : "is not a folder."; | ||
| System.out.println("\"" + name + "\" " + isFolderString); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Downloads file from the server to the file with specified name. If file with | ||
| * the given name already exists, FileAlreadyExistsException will be thrown. | ||
| * | ||
| * @param source target file. | ||
| * @param destination path, to save file. | ||
| * @throws IOException if any IOException occurred. | ||
| */ | ||
| public void get(@NotNull final String source, @NotNull final String destination) throws IOException { | ||
| os.writeInt(2); | ||
| os.writeUTF(source); | ||
| os.flush(); | ||
|
|
||
| final File file = new File(destination); | ||
| if (!file.createNewFile()) { | ||
| throw new FileAlreadyExistsException(); | ||
| } | ||
| final byte[] buf = new byte[BUF_SIZE]; | ||
| try (final FileOutputStream os = new FileOutputStream(file)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Давайте попытаемся избежать ручного манипулирования байтовыми буферами и воспользуемся
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Исправил. Для отправки файла тоже можно было бы использовать такой способ, но, к сожалению, описанный интерфейс абстрактной сессии не позваляет. Менять же его ради одноразовай задачи не считаю логичным. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Мне скорее реализация нетривиальной логики руками кажется не очень логичной. |
||
| final long size = is.readLong(); | ||
| IOUtils.copyLarge(is, os, 0, size); | ||
| } | ||
| } | ||
|
|
||
| private class FileAlreadyExistsException extends RuntimeException {} | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А можно сделать интерфейс клиента таким, чтобы его можно было безболезненно переиспользовать для GUI?
Пока -1