Java печатает одну консольную строку с X [дубликат]

Добавление случая, когда имя класса для объекта, используемого в структуре сущности, такое же, как имя класса для файла с кодировкой веб-формы.

Предположим, у вас есть веб-форма Contact.aspx, чей класс codebehind Свяжитесь с вами, и у вас есть имя объекта Contact.

Затем следующий код вызовет исключение NullReferenceException при вызове context.SaveChanges ()

Contact contact = new Contact { Name = "Abhinav"};
var context = new DataContext();
context.Contacts.Add(contact);
context.SaveChanges(); // NullReferenceException at this line

Ради полноты класса DataContext

public class DataContext : DbContext 
{
    public DbSet Contacts {get; set;}
}

и класс сущности контакта. Иногда классы сущностей являются частичными классами, так что вы можете распространять их и в других файлах.

public partial class Contact 
{
    public string Name {get; set;}
}

Ошибка возникает, когда оба класса entity и codebehind находятся в одном и том же пространстве имен. Чтобы исправить это, переименуйте класс сущности или класс codebehind для Contact.aspx.

Причина. Я все еще не уверен в причине. Но всякий раз, когда какой-либо из классов сущностей расширяет System.Web.UI.Page, возникает эта ошибка.

Для обсуждения рассмотрим NullReferenceException в DbContext.saveChanges ()

30
задан masher 17 August 2009 в 07:36
поделиться

6 ответов

Нет надежных кросс-платформенных решений этой проблемы. Действительно, бывают ситуации, когда невозможно узнать, какова реальная ширина консоли.

Например, в системе Linux вы обычно можете узнать условные размеры терминала из переменных среды LINES и COLUMNS. Хотя эти переменные автоматически обновляются при изменении размеров окон «эмулятора терминала», это не всегда так. Действительно, в случае удаленной консоли, подключенной по протоколу telnet, нет способа получить фактические размеры терминала в оболочке пользователя.

EDIT: просто добавьте это, если пользователь изменит размеры своего / xterm в Linux после запуска приложения Java, приложение Java не будет уведомлено и не увидит новые измерения, отраженные в его копии переменных среды LINES и COLUMNS!

EDIT 2: Моя ошибка, они bash переменные оболочки, но не экспортируются в среду по умолчанию. Вы можете «исправить» это, запустив export COLUMNS LINES перед запуском приложения Java.

24
ответ дан Stephen C 1 September 2018 в 00:29
поделиться
  • 1
    Я надеялся, что будет что-то, что вернет ширину / высоту и т. Д. Или -1, если это невозможно определить ... ну ладно. Приветствуем жестко закодированные константы! – masher 18 August 2009 в 00:22
  • 2
    @masher: проблема в том, что в Linux ответ почти всегда должен быть «не может быть определен с какой-либо определенностью». – Stephen C 18 August 2009 в 00:29
  • 3
    Я попытался сделать это с помощью System.getenv («COLUMNS»), но он вернул значение null. Ubuntu 10.04 / GNOME 2.30.2 – jsj 4 May 2011 в 05:25
  • 4
    Я использую скрипт для вызова моего приложения Java, а сценарий выполняет eval `resize`; export COLUMNS перед вызовом Java под Linux. – Ogre Psalm33 20 September 2011 в 19:54
  • 5
    @Ogre Psalm33 - это работает до определенной степени. Но если пользователь вручную изменит размер окна консоли после запуска приложения Java, приложение все равно будет использовать старый размер. Это один из аспектов «не может быть определен с уверенностью». ... – Stephen C 21 September 2011 в 02:36

Редактирование: см. комментарий @ dave_thompson_085 о ProcessBuilder, так как это почти наверняка лучший подход.

Еще один ответ упоминал, что вы запускаете tput cols в скрипте перед началом вашей команды. Но если вы хотите запустить его после того, как Java уже запущена, используя Runtime.getRuntime().exec(), вы обнаружите, что tput не может разговаривать с вашим терминалом, потому что Java перенаправляет stdout и stderr. В качестве обходного решения, не используемого для всех, вы можете использовать магическое устройство /dev/tty, которое относится к терминалу текущего процесса. Это позволяет вам запускать что-то вроде этого:

Process p = Runtime.getRuntime().exec(new String[] {
    "bash", "-c", "tput cols 2> /dev/tty" });
// Read the output of this process to get your terminal width

Это работает для меня в Linux, но я бы не ожидал, что он будет работать повсюду. Он, надеюсь, будет работать на Mac. Это определенно не будет работать в Windows, хотя это может быть с Cygwin.

8
ответ дан Jack O'Connor 1 September 2018 в 00:29
поделиться
  • 1
    Работает также на Mac – pascal 29 July 2014 в 00:39
  • 2
    Это единственное решение, которое работает для меня. – Panayotis 22 May 2017 в 12:50
  • 3
    ProcessBuilder, поскольку Java7 (2011) может передать собственный stdin / out / err для Java в дочерний процесс вместо перенаправленных по умолчанию каналов; см. inheritIO() и redirect*(Redirect.INHERIT) - что не помогает, если пользователь java был перенаправлен пользователем, но в этом случае почему вы заботитесь о ширине устройства ввода-вывода, которое вы не используете? – dave_thompson_085 11 September 2017 в 00:24

Java 6 имеет класс java.io.Console, но, к сожалению, он не имеет требуемой функциональности. Получение ширины окна консоли невозможно в стандартной библиотеке Java и чистой межплатформенной Java.

Вот альтернативная консольная библиотека Java , которая позволяет получить размер экрана , но он включает в себя DLL для Windows. Возможно, вы сможете взять исходный код и скомпилировать часть C в общую библиотеку Linux или Mac OS X, чтобы она также работала на этих платформах.

4
ответ дан Jesper 1 September 2018 в 00:29
поделиться
  • 1
    Я нашел API консоли и был взволнован; и тогда я не был ... Ибо то, что я хочу сделать, изучение C и как кросс-компиляция вроде как забивает гвоздь с помощью разрушающего шара. – masher 18 August 2009 в 00:20
  • 2
    @Jesper - на самом деле это не ошибка Java. Есть много вещей, которые делают невозможным получение текущего размера консоли во всех случаях на машине Linux / Unix. – Stephen C 21 September 2011 в 02:38

Я уже работал над этой проблемой. Я использую несколько разных методов. Однако сложно иметь по-настоящему кросс-платформенное решение.

Я попытался сделать что-то вроде этого:

String os = System.getProperty("os.name").toLowerCase();

    //Windows
    if(os.contains("win")){
        System.out.append("Windows Detected");
        //set Windows Dos Terminal width 80, height 25
        Process p = Runtime.getRuntime().exec("mode 80, 25");
    }
    //Mac
    if(os.contains("mac")){
        System.out.println("Macintosh Detected");
        //... I dont know...try Google
    }
    //Linux
    if(os.contains("linux")){
        System.out.println("Linux Detected");

Вы можете читать / тестировать и добавлять «экспорт COLUMNS» в файл .bashrc в каждом домашнем каталоге Linux для Linux с помощью String .contains ("export COLUMNS") и свойство user.dir.

Это позволит вам загружать столбцы каждый раз при запуске приложения java.

Затем я передам его в файл temp. Например:

try {
    ProcessBuilder pb = new ProcessBuilder("bash","-c","echo $COLUMNS >/home/$USER/bin/temp.txt" );  
        pb.start();

    }catch (Exception e) {
        System.out.println("exception happened - here's what I know: ");
        e.printStackTrace();
        System.exit(-1);
    }
}

Другой вариант, который у вас есть, - выполнить yor Java.jar с помощью скрипта bash при запуске. Внутри скрипта вы можете использовать «tput cols» для получения ширины. Затем передайте это значение вашему Java-приложению как String [] arg.

Так вот:

//#!/bin/bash

//#clear the screen

clear 

//#get the console width and height

c=$[$(tput cols)]

l=$[$(tput lines)]

//#pass the columns, lines and an optional third value as String[] args.

java -jar ~/bin/Plus.jar $c $l $1

почему эта сложная задача с Java? Очевидно, хорошее место для написания хорошего API. Думаю, мы могли бы попробовать Apache.commons.exec?

2
ответ дан marc_s 1 September 2018 в 00:29
поделиться
  • 1
    Если export COLUMNS был вызван до начала процесса Java, вы можете просто сделать System.getenv("COLUMNS"); нет необходимости запускать подпроцесс с ProcessBuilder. – dimo414 15 February 2016 в 13:59

Python, похоже, имеет хорошее решение: 11.9.3. Запрос размера выходного терминала . Я бы не задерживал дыхание, ожидая, что это будет доступно в основной Java, но вы могли бы использовать Jython , чтобы сделать доступную функциональность Python.

16
ответ дан Michael Scheper 1 September 2018 в 00:29
поделиться
  • 1
    Как упоминают shutil документы, это возвращается к os.get_terminal_size() , который является специфичным для ОС и реализован в C. Использование Jython может работать для некоторых случаев использования, но это довольно тяжелый молот. – dimo414 15 February 2016 в 14:16
  • 2
    В Unix JLine просто вызывает stty -a в TerminalLineSetting , а в Windows он подключается к закрытой части библиотеки JAnsi через org.fusesource.jansi.internal.WindowsSupport. – dimo414 15 February 2016 в 14:33
  • 3
    Для JLine3 это будет "org.jline.terminal.TerminalBuilder.terminal (). GetWidth () & quot; – Mark 29 June 2018 в 19:47

Для меня единственный способ получить представление о окне терминала (все еще неверно, когда изменяется размер окна) - использовать команду типа

ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", "mode con");
pb.redirectError(ProcessBuilder.Redirect.INHERIT);

. При запуске без части cmd.exe , это показывает, что команда не найдена. Также обратите внимание на часть redirectError. Если не используется, тогда будет использоваться размер вывода Java, а не фактический. Только с этой комбинацией можно было захватить фактический размер.

0
ответ дан Panayotis 1 September 2018 в 00:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: