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

Kotlin - przesyłanie plików przez ftp + zapis i czytanie danych z pliku.
Waran3
  • Rejestracja:około 4 lata
  • Ostatnio:około rok
  • Lokalizacja:Zielonka
  • Postów:103
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:

Kopiuj
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. ;-)


edytowany 1x, ostatnio: Waran3
Waran3
  • Rejestracja:około 4 lata
  • Ostatnio:około rok
  • Lokalizacja:Zielonka
  • Postów:103
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.

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

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

Kopiuj
client.storeFile(filename, `is`)

Kopiuj




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


edytowany 1x, ostatnio: Waran3
Waran3
  • Rejestracja:około 4 lata
  • Ostatnio:około rok
  • Lokalizacja:Zielonka
  • Postów:103
0

Utknąłem na stringu...

Kopiuj
// 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:

Kopiuj
 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 ;-)

Kopiuj
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ę...


edytowany 1x, ostatnio: Waran3
Waran3
  • Rejestracja:około 4 lata
  • Ostatnio:około rok
  • Lokalizacja:Zielonka
  • Postów:103
0

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

Działający kod:

Kopiuj
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()
        }
    }
}


edytowany 1x, ostatnio: Waran3
Waran3
  • Rejestracja:około 4 lata
  • Ostatnio:około rok
  • Lokalizacja:Zielonka
  • Postów:103
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


edytowany 2x, ostatnio: Waran3
Waran3
  • Rejestracja:około 4 lata
  • Ostatnio:około rok
  • Lokalizacja:Zielonka
  • Postów:103
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). :-)

Kopiuj
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:

Kopiuj
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
                    )


                }
            }
        }
    }


edytowany 2x, ostatnio: Waran3
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)