Kotlin - przesyłanie plików przez ftp + zapis i czytanie danych z pliku.

0

Wiem, że ftp to przeszłość itd. ale jak do tej pory w ten właśnie sposób wrzucałem pliki na
moje strony www...i chciałbym to wykorzystać choć pewnie jest lepszy aktualnie sposób ale wyjdźmy od tego. :-)

Co potrzebuję zrobić?
Po pierwsze chcę zapisać dane do 3 plików(txt) z 3 różnych urządzeń.
Pewnie układ wspólnej bazy danych był by lepszy ale póki co idę tą drogą...
Zapis mam powiedzmy przerobiony ale mam też kilka kłopotliwych dla mnie miejsc, z którymi nie mogę sobie poradzić.
Po pierwsze zapis musi działać na zasadzie dopisywania do istniejącego już pliku.
Niby jest append ale jakoś nie mogę opanować zapisu żeby część była w jednej linii
a cześć w kolejnych.

Np.

Sędzia 1, pojedynek 1, zawodnik 1
Wynik = 32

Sędzia 1 , pojedynek 1, zawodnik 2
Wynik = 55

Sędzia 1 , pojedynek 1, zawodnik 3
Wynik = 12

(...)

Sędzia 1 , pojedynek 2, zawodnik 5
Wynik = 44

Sędzia 1 , pojedynek 2, zawodnik 6
Wynik = 23

(...)

Czyli chciał bym aby te kolejne grupy( tekstu) dopisywały się właśnie w podobny sposób.
Klikam "zapisz wynik" i program dopisuje kolejne takie dwie linijki tekstu do pliku.
Pewnie trywialne ale ... ;-)

Zapisanie tych plików lokalnie to pikuś ale takich plików ma być 3 i na ich bazie musi powstać
plik wynikowy. Stąd właśnie potrzeba jakiegoś wspólnego miejsca sieciowego skąd te pliki
mogły by zostać pobrane.
No i tutaj mam ten serwer ftp.
Przeszukując sieć znalazłem kod do tego typu operacji:

try {
    val mFtpClient = FTPClient()
    mFtpClient.connect("hots", PORT)
    mFtpClient.login("user", "password")
    mFtpClient.type = FTPClient.TYPE_BINARY
    mFtpClient.changeDirectory("/directory_path/")

    mFtpClient.upload(File("file_path"))
    mFtpClient.disconnect(true)

} catch (e: Exception) {
    e.printStackTrace()
}

Oraz bibliotekę z której należy skorzystać:
You can use ftp4j library by download ftp4j-1.7.2.jar.

Niestety nie chce mi to działać albo raczej ...czegoś nie umiem zrobić

Bibliotekę zainstalowałem
screenshot-20220419113036.png
Na czerwono mam:
FTPClient()
PORT
File

Podkreślone na czerwono:
.type

Jak to zadziała to program ma pobrać konkretne wartości z plików i przeprowadzić
obliczenia. Obliczenia są banalne ale rozpoznawanie, o które konkretnie liczby chodzi
już nieco trudniejsze.

To taki zarys tego co potrzebuję zrobić.
Cierpliwych bardzo proszę o wskazówki ;-)a pozostałych błagam o powstrzymanie się od uwag ...moralizujących. ;-)

0

Przesyłanie pliku na ftp...( org.apache.commons.net.ftp )
Działa...ale tylko trochę :-)
Mogę jedynie przesłać pusty plik.
Podanie nazwy ze ścieżką nie działa tzn. nic nie zostaje przesłane na ftp.

var filename = "t:/kotlin/mk_1.txt"

Czyli ta linia kodu nie kuma tej ścieżki.

client.storeFile(filename, `is`)





Tu cały kod:
```kotlinfun main(args: Array<String>) {
        val client = FTPClient()
        var filename = "t:/kotlin/mk_1.txt"

        // Read the file from resources folder.
        val classLoader = Thread.currentThread().contextClassLoader
        try {
            classLoader.getResourceAsStream(filename).use { `is` ->
                client.connect("ftp.test.com.pl")
                val login: Boolean = client.login("name", "123456")
                if (login) {
                    println("Logowanie z sukcesem")
                    println ("$filename")

                    // Store file to server
                    client.storeFile(filename, `is`)
                    client.logout()
                }
            }
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            try {
                client.disconnect()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }

Po podaniu jedynie samej nazwy pliku ( mk1_txt ), taki plik zostaje utworzony ale zwrotnie dostaję listę błędów:

Logowanie z sukcesem
mk_1.txt
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.io.InputStream.read(byte[])" because "source" is null
at org.apache.commons.net.io.Util.copyStream(Util.java:102)
at org.apache.commons.net.ftp.FTPClient._storeFile(FTPClient.java:675)
at org.apache.commons.net.ftp.FTPClient.__storeFile(FTPClient.java:639)
at org.apache.commons.net.ftp.FTPClient.storeFile(FTPClient.java:2030)
at Test_mk_2Kt.main(test_mk_2.kt:73)

Process finished with exit code 1

0

Utknąłem na stringu...

// Store file to server
                    client.storeFile(filename, `is`)

Tu gdzie jest "is" powinien być string...nie umiem tego zrobić.
To co jest aktualnie, nie działa:

 val classLoader = Thread.currentThread().contextClassLoader
        try {
            classLoader.getResourceAsStream(filename).use { `is` ->
                client.connect("ftp.test.com.pl")
                val login: Boolean = client.login("name", "123456")
                if (login) {
                    println("Logowanie z sukcesem")
                    println ("$filename")

                    // Store file to server
                    client.storeFile(filename, `is`)
                    client.logout()
                }
            }

To znaczy loguję się do ftp ale nie mogę przesłać pliku.

Próbowałem inaczej określić string ale niestety brakuje wiedzy ;-)

Val si = FileInputStream(File("t:/kotlin/mk.txt"))

To nie działa...tak jak bym się spodziewał :-) ale kierunek był dobry, jak się okazuje;-)

Może ktoś wrzuci choć małą wskazówkę...

0

Temat FTP przewalczony ...chyba.;-) Siła internetu! Pomógł kolega z Indonezji. ;-) https://kodejava.org/

Działający kod:

import org.apache.commons.net.ftp.FTPClient
import java.io.FileInputStream

fun main() {
    val client = FTPClient()
    val filename = "t:/kotlin/mk.txt"
    FileInputStream(filename).use {
        client.connect("ftp.test.com.pl")
        val login = client.login("login", "password")

        if (login) {
            client.storeFile("abc.txt", it)

            client.logout()
            client.disconnect()
        }
    }
}

0

Wysłać plik na ftp udało się ale teraz jak taki plik ściągnąć w druga stronę albo jak go czytać?
Pytanie... jak wskazać ( ściezka ) plik na serwerze ftp? :-)
Nie wspomnę już o zapisywaniu plików w androidzie...tu to już można pokusić się o doktorat.

Dla porządku wrzucam tutaj kilka linków dotyczących plików w androidzie.
https://stackoverflow.com/questions/45193941/how-to-read-and-write-txt-files-in-android-in-kotlin
https://developer-android-com.translate.goog/training/data-storage/app-specific?_x_tr_sl=en&_x_tr_tl=pl&_x_tr_hl=pl&_x_tr_pto=op%2Cwapp

Te opisy wnoszą sporą dawkę optymizmu ale nie wiem czemu context wszędzie gdzie go użyję świeci się na czerwono.
screenshot-20220424144410.png

0

W między czasie ogarnąłem sposób przesłania Stringa do ftp z pominięciem kopiowania pliku.
To próba walki z zapisem pliku na androidzie :-)
Niestety ciągle nie umiem spowodować żeby ten program wykonał się w połączeniu z Jetpack Compose ( czytam). :-)

fun zapis_string_ftp() {
    val client = FTPClient()
    val text: String = "Hello World!"
    val inputStream = text.byteInputStream(Charsets.UTF_8)

    //val filename = "t:/kotlin/mk.txt"
    inputStream.use {
        client.connect("ftp.test.com.pl")
        val login = client.login("login", "password")

        if (login) {
            client.storeFile("abc.txt", it)
            println("it = $it")

            client.logout()
            client.disconnect()
        }
    }
}

Jestem krok dalej.
Utworzyłem cały ten sos...czyli HomeViewState... HomeViewModel.
Dołożyłem "viewModelScope.launch(Dispatchers.IO) { " - w HomeViewModel.
Zadziałało ale nie tworzy się plik na ftp.
Niby wszytko jest ok ale pliku nie ma. :-)Tak jakby storeFile nie działał.
Kod po tych wszystkich perturbacjach wygląda tak:

private fun zapis_string_ftp() {
        viewModelScope.launch(Dispatchers.IO) {
            val client = FTPClient()
            val text: String = "Hello World!"
            val inputStream = text.byteInputStream(Charsets.UTF_8)

          
            inputStream.use {
                client.connect("ftp.test.com.pl")
                val login = client.login("login", "password")

                if (login) {
                    client.storeFile("abc.txt", it)
                    println("it = $it")
                    println("Client = $client")
                    println("Text = $text")

                    client.logout()
                    client.disconnect()
                    val a = Math.random()
                    val b = Math.random()

                    _viewState.value = viewState.value.copy(
                        result = a + b
                    )


                }
            }
        }
    }

1 użytkowników online, w tym zalogowanych: 0, gości: 1